重命名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

我将专注于两件事情:

  1. OP明确指出

    我有编辑的列名称存储在列表中,但我不知道如何replace列名称。

    我不想解决如何replace'$'或从每个列标题剥离第一个字符的问题。 OP已经完成了这一步。 相反,我想专注于用一个新的replace列名replace现有的columns对象。

  2. 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
这是一个带有transposeset_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聊天中的人们指出的,如果我在xy之间添加一个* ,我可以保护我的yvariables。 虽然在这方面我不相信需要保护。 这仍然值得一提。

 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方法添加了可能被设置为columns1axis参数。 此更新使得此方法与pandasAPI的其余部分相匹配。 它仍然有indexcolumns参数,但你不再被迫使用它们。
  • set_index设置为Falseset_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]