重命名pandas列
我有一个数据表使用pandas和列标签,我需要编辑,以取代原来的列标签。
我想要更改数据表A
中原始列名称所在的列名称:
['$a', '$b', '$c', '$d', '$e']
至
['a', 'b', 'c', 'd', 'e'].
我有编辑的列名称存储在列表中,但我不知道如何replace列名称。
只要将它分配给.columns
属性:
>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]}) >>> df.columns = ['a', 'b'] >>> df ab 0 1 10 1 2 20
使用重命名function并引用要重命名的列。 不是所有的列都必须重命名:
df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'}) # OR df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'}, inplace=True)
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html
rename
方法可以采取一个函数,例如:
In [11]: df.columns Out[11]: Index([u'$a', u'$b', u'$c', u'$d', u'$e'], dtype=object) In [12]: df.rename(columns=lambda x: x[1:], inplace=True) In [13]: df.columns Out[13]: Index([u'a', u'b', u'c', u'd', u'e'], dtype=object)
既然你只想删除所有列名中的$符号,你可以这样做:
df = df.rename(columns=lambda x: x.replace('$', ''))
要么
df.rename(columns=lambda x: x.replace('$', ''), inplace=True)
如http://pandas.pydata.org/pandas-docs/stable/text.html中所logging:;
df.columns = df.columns.str.replace('$','')
df.columns = ['a', 'b', 'c', 'd', 'e']
它将按照您提供的顺序,用您提供的名称replace现有名称。
你也可以像这样通过索引来分配它们:
df.columns.values[2] = 'c' #renames the 2nd column to 'c'
old_names = ['$a', '$b', '$c', '$d', '$e'] new_names = ['a', 'b', 'c', 'd', 'e'] df.rename(columns=dict(zip(old_names, new_names)), inplace=True)
这样你可以手动编辑new_names
如你所愿。 当您只需要重新命名几列来纠正拼写错误,重音符号,删除特殊字符
列名与系列的名称
我想解释一下幕后发生的事情。
数据框是一组系列。
系列又是numpy.array
的延伸
numpy.array
有一个属性.name
这是系列的名字。 大pandas很less尊重这个属性,但是它在某些地方徘徊,可以用来攻击一些pandas的行为。
命名列的列表
这里的很多答案都谈到了df.columns
属性是一个list
,实际上它是一个Series
。 这意味着它有一个.name
属性。
这是如果你决定填写列的名称Series
:
df.columns = ['column_one', 'column_two'] df.columns.names = ['name of the list of columns'] df.index.names = ['name of the index'] name of the list of columns column_one column_two name of the index 0 4 1 1 5 2 2 6 3
请注意,索引的名称总是低一列。
徘徊的文物
.name
属性有时会.name
。 如果你设置了df.columns = ['one', 'two']
那么df.one.name
将是'one'
。
如果你设置df.one.name = 'three'
那么df.columns
仍然会给你['one', 'two']
,而df.one.name
会给你'three'
但
pd.DataFrame(df.one)
将返回
three 0 1 1 2 2 3
因为pandas重复使用已定义的Series
的.name
。
多级别的列名称
pandas有做多层列名的方法。 这里没有太多的魔法,但是我也想在我的回答中加以说明,因为我没有看到有人在这里捡到这些东西。
|one | |one |two | 0 | 4 | 1 | 1 | 5 | 2 | 2 | 6 | 3 |
通过将列设置为列表可以轻松实现,如下所示:
df.columns = [['one', 'one'], ['one', 'two']]
一条线或pipe道解决scheme
我将专注于两件事情:
-
OP明确指出
我有编辑的列名称存储在列表中,但我不知道如何replace列名称。
我不想解决如何replace
'$'
或从每个列标题剥离第一个字符的问题。 OP已经完成了这一步。 相反,我想专注于用一个新的replace列名replace现有的columns
对象。 -
df.columns = new
其中new
是新列名的列表,就像它获得的那样简单。 这种方法的缺点是它需要编辑现有的数据框的columns
属性,而不是内联。 我将通过stream水线显示几种方法来执行此操作,而无需编辑现有数据框。
设置1
为了专注于需要重新命名用已有列表replace列名,我将创build一个新的示例数据框df
其中包含初始列名和不相关的新列名。
df = pd.DataFrame({'Jack': [1, 2], 'Mahesh': [3, 4], 'Xin': [5, 6]}) new = ['x098', 'y765', 'z432'] df Jack Mahesh Xin 0 1 3 5 1 2 4 6
解决scheme1
pd.DataFrame.rename
已经有人说过, 如果你有一个字典将旧的列名映射到新的列名,你可以使用pd.DataFrame.rename
。
d = {'Jack': 'x098', 'Mahesh': 'y765', 'Xin': 'z432'} df.rename(columns=d) x098 y765 z432 0 1 3 5 1 2 4 6
但是,您可以轻松创build该字典并将其包含在调用中以rename
。 以下利用了在迭代df
时迭代每个列名的事实。
# given just a list of new column names df.rename(columns=dict(zip(df, new))) x098 y765 z432 0 1 3 5 1 2 4 6
如果您的原始列名称是唯一的,这很好用。 但是,如果不是,那么这就打破了。
安装程序2
非唯一的列
df = pd.DataFrame( [[1, 3, 5], [2, 4, 6]], columns=['Mahesh', 'Mahesh', 'Xin'] ) new = ['x098', 'y765', 'z432'] df Mahesh Mahesh Xin 0 1 3 5 1 2 4 6
解决scheme2
pd.concat
使用keys
参数
首先,注意当我们尝试使用解决scheme1时会发生什么情况:
df.rename(columns=dict(zip(df, new))) y765 y765 z432 0 1 3 5 1 2 4 6
我们没有将new
列表映射为列名。 我们结束了重复y765
。 相反,我们可以在遍历df
的列时使用pd.concat
函数的keys
参数。
pd.concat([c for _, c in df.items()], axis=1, keys=new) x098 y765 z432 0 1 3 5 1 2 4 6
解决scheme3
重build。 这应该只用于所有列都有单个dtype
的情况。 否则,你将会得到所有列的dtype
object
,并将它们转换回来需要更多的字典工作。
单dtype
pd.DataFrame(df.values, df.index, new) x098 y765 z432 0 1 3 5 1 2 4 6
混合dtype
pd.DataFrame(df.values, df.index, new).astype(dict(zip(new, df.dtypes))) x098 y765 z432 0 1 3 5 1 2 4 6
解决scheme4
这是一个带有transpose
和set_index
的噱头戏法。 pd.DataFrame.set_index
允许我们设置一个内联索引,但是没有对应的set_columns
。 所以我们可以转置,然后set_index
,并转置回来。 然而,解决scheme3中的相同的单一dtype
与混合dtype
警告适用于此处。
单dtype
df.T.set_index(np.asarray(new)).T x098 y765 z432 0 1 3 5 1 2 4 6
混合dtype
df.T.set_index(np.asarray(new)).T.astype(dict(zip(new, df.dtypes))) x098 y765 z432 0 1 3 5 1 2 4 6
解决scheme5
在pd.DataFrame.rename
中使用循环遍历new
每个元素的lambda
在这个解决scheme中,我们传递一个需要x
的lambda,但是忽略它。 它也需要一个y
但不指望它。 相反,迭代器是作为默认值给出的,然后我可以使用它循环一次,而不考虑x
的值是什么。
df.rename(columns=lambda x, y=iter(new): next(y)) x098 y765 z432 0 1 3 5 1 2 4 6
正如sopython聊天中的人们指出的,如果我在x
和y
之间添加一个*
,我可以保护我的y
variables。 虽然在这方面我不相信需要保护。 这仍然值得一提。
df.rename(columns=lambda x, *, y=iter(new): next(y)) x098 y765 z432 0 1 3 5 1 2 4 6
pandas0.21+答案
在0.21版本中对列重命名进行了一些重大更新。
-
rename
方法添加了可能被设置为columns
或1
的axis
参数。 此更新使得此方法与pandasAPI的其余部分相匹配。 它仍然有index
和columns
参数,但你不再被迫使用它们。 - 将
set_index
设置为False
的set_index
方法使您可以使用列表重命名所有索引或列标签。
pandas0.21+的例子
构build示例DataFrame:
df = pd.DataFrame({'$a':[1,2], '$b': [3,4], '$c':[5,6], '$d':[7,8], '$e':[9,10]}) $a $b $c $d $e 0 1 3 5 7 9 1 2 4 6 8 10
使用axis='columns'
或axis=1
rename
df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis='columns')
要么
df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis=1)
两者的结果如下:
abcde 0 1 3 5 7 9 1 2 4 6 8 10
仍然可以使用旧的方法签名:
df.rename(columns={'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'})
rename
函数还接受将应用于每个列名称的函数。
df.rename(lambda x: x[1:], axis='columns')
要么
df.rename(lambda x: x[1:], axis=1)
使用set_axis
与列表和set_axis
inplace=False
您可以向set_axis
方法提供一个长度等于列数(或索引)的列表。 目前, inplace
默认为True
,但在将来的发行版中, inplace
将被默认为False
。
df.set_axis(['a', 'b', 'c', 'd', 'e'], axis='columns', inplace=False)
要么
df.set_axis(['a', 'b', 'c', 'd', 'e'], axis=1, inplace=False)
为什么不使用df.columns = ['a', 'b', 'c', 'd', 'e']
?
直接分配列没有任何问题。 这是一个非常好的解决scheme。
使用set_axis
的优点是它可以用作方法链的一部分,并返回DataFrame的新副本。 没有它,你将不得不将链的中间步骤存储到另一个variables,然后重新分配列。
# new for pandas 0.21+ df.some_method1() .some_method2() .set_axis() .some_method3() # old way df1 = df.some_method1() .some_method2() df1.columns = columns df1.some_method3()
如果你有数据框,df.columns将所有内容转储到你可以操纵的列表中,然后重新分配到你的数据框中作为列的名字。
columns = df.columns columns = [row.replace("$","") for row in columns] df.rename(columns=dict(zip(columns, things)), inplace=True) df.head() #to validate the output
最好的办法? IDK。 一种方式 – 是的。
评估问题答案中提出的所有主要技术的更好的方法是使用cProfile来测量内存和执行时间。 @ kadee,@kaitlyn和@eumiro的执行时间最快,尽pipe这些函数的速度非常快,但我们正在比较所有答案的.000和.001秒的四舍五入。 道德:我上面的答案可能不是“最好的”方式。
import pandas as pd import cProfile, pstats, re old_names = ['$a', '$b', '$c', '$d', '$e'] new_names = ['a', 'b', 'c', 'd', 'e'] col_dict = {'$a': 'a', '$b': 'b','$c':'c','$d':'d','$e':'e'} df = pd.DataFrame({'$a':[1,2], '$b': [10,20],'$c':['bleep','blorp'],'$d':[1,2],'$e':['texa$','']}) df.head() def eumiro(df,nn): df.columns = nn #This direct renaming approach is duplicated in methodology in several other answers: return df def lexual1(df): return df.rename(columns=col_dict) def lexual2(df,col_dict): return df.rename(columns=col_dict, inplace=True) def Panda_Master_Hayden(df): return df.rename(columns=lambda x: x[1:], inplace=True) def paulo1(df): return df.rename(columns=lambda x: x.replace('$', '')) def paulo2(df): return df.rename(columns=lambda x: x.replace('$', ''), inplace=True) def migloo(df,on,nn): return df.rename(columns=dict(zip(on, nn)), inplace=True) def kadee(df): return df.columns.str.replace('$','') def awo(df): columns = df.columns columns = [row.replace("$","") for row in columns] return df.rename(columns=dict(zip(columns, '')), inplace=True) def kaitlyn(df): df.columns = [col.strip('$') for col in df.columns] return df print 'eumiro' cProfile.run('eumiro(df,new_names)') print 'lexual1' cProfile.run('lexual1(df)') print 'lexual2' cProfile.run('lexual2(df,col_dict)') print 'andy hayden' cProfile.run('Panda_Master_Hayden(df)') print 'paulo1' cProfile.run('paulo1(df)') print 'paulo2' cProfile.run('paulo2(df)') print 'migloo' cProfile.run('migloo(df,old_names,new_names)') print 'kadee' cProfile.run('kadee(df)') print 'awo' cProfile.run('awo(df)') print 'kaitlyn' cProfile.run('kaitlyn(df)')
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})
如果您的新列的列表与现有列的顺序相同,则分配很简单:
new_cols = ['a', 'b', 'c', 'd', 'e'] df.columns = new_cols >>> df abcde 0 1 1 1 1 1
如果您将旧字段名称的字典键入新列名称,则可以执行以下操作:
d = {'$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'} df.columns = df.columns.map(lambda col: d[col]) # Or `.map(d.get)` as pointed out by @PiRSquared. >>> df abcde 0 1 1 1 1 1
如果你没有列表或字典映射,你可以通过列表理解去掉前面的$
符号:
df.columns = [col[1:] if col[0] == '$' else col for col in df]
另一种替代原始列标签的方法是从原始列标签中去除不需要的字符(这里是'$')。
这可以通过在df.columns上运行一个for循环并将删除的列添加到df.columns来完成。
相反,我们可以通过使用如下的列表理解,在一个声明中整齐地做到这一点:
df.columns = [col.strip('$') for col in df.columns]
(Python中的strip
方法从string的开始和结尾剥离给定的字符。)
真正简单的使用
df.columns = ['Name1', 'Name2', 'Name3'...]
它将按照您放置的顺序分配列名称
你可以使用str.slice
:
df.columns = df.columns.str.slice(1)
我知道这个问题和答案已被咀嚼死亡。 但是我提到它是为了解决我遇到的一个问题。 我能够用不同的答案零碎解决它,因此提供我的反应,以防万一需要它。
我的方法是通用的,其中你可以添加额外的分隔符逗号分隔delimiters=
variables和面向未来的delimiters=
。
工作代码:
import pandas as pd import re df = pd.DataFrame({'$a':[1,2], '$b': [3,4],'$c':[5,6], '$d': [7,8], '$e': [9,10]}) delimiters = '$' matchPattern = '|'.join(map(re.escape, delimiters)) df.columns = [re.split(matchPattern, i)[1] for i in df.columns ]
输出:
>>> df $a $b $c $d $e 0 1 3 5 7 9 1 2 4 6 8 10 >>> df abcde 0 1 3 5 7 9 1 2 4 6 8 10
DataFrame – df.rename()将工作。
df.rename(columns = {'Old Name':'New Name'})
df是你有的DataFrame, 旧名称是你想改变的列名,那么New Name是你改变的新名字。 这种DataFrame内置方法使事情变得更容易。
请注意,这些方法不适用于MultiIndex。 对于MultiIndex,您需要执行以下操作:
>>> df = pd.DataFrame({('$a','$x'):[1,2], ('$b','$y'): [3,4], ('e','f'):[5,6]}) >>> df $a $be $x $yf 0 1 3 5 1 2 4 6 >>> rename = {('$a','$x'):('a','x'), ('$b','$y'):('b','y')} >>> df.columns = pandas.MultiIndex.from_tuples([ rename.get(item, item) for item in df.columns.tolist()]) >>> df abe xyf 0 1 3 5 1 2 4 6
如果您不得不处理由您的控制系统提供的系统命名的列的负载,我提出了以下方法,一次性使用一般方法和特定replace。
我首先使用正则expression式从数据框列名称中创build一个字典,以便丢弃列名的某些附录,然后向字典中添加特定的replace项,以便在接收数据库中稍后预期的名称为核心列。
然后将其一次应用于数据框。
dict=dict(zip(df.columns,df.columns.str.replace('(:S$|:C1$|:L$|:D$|\.Serial:L$)',''))) dict['brand_timeseries:C1']='BTS' dict['respid:L']='RespID' dict['country:C1']='CountryID dict['pim1:D']='pim_actual' df.rename(columns=dict, inplace=True)
如果你不想要行名df.columns = ['a', 'b',index=False]