在Pandas中重命名列名

2934
我想要更改Pandas DataFrame的列标签从
['$a', '$b', '$c', '$d', '$e']

to

['a', 'b', 'c', 'd', 'e']

9
您可能希望查看官方文档,其中包含有关重命名列标签的内容:https://pandas.pydata.org/pandas-docs/stable/user_guide/text.html - ccpizza
2
已浏览 5.6 百万次。这告诉我们 Pandas 是多么直观易用。 - mins
@mins 你想要什么?你更喜欢什么?dplyr?Spark?Polars?你只是根据一个问题的观点来评判整个库吗?做一个好的用户,而不是消极地思考。最好你看看pandas在SO上有多少问题,pandas正在接近最好的语言。 - rubengavidia0x
2
@rubengavidia0x:虽然我认为Pandas很强大,但我不认为我们可以说它易于使用。正如在这篇文章中指出的那样,已经有35种不同的方法来回答关于重命名列(重命名列...)的问题。 (https://www.dunderdata.com/blog/minimally-sufficient-pandas) - mins
36个回答

4487

重命名特定列

使用df.rename()函数并引用要重命名的列。并非所有列都需要重命名:

df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})

# Or rename the existing DataFrame (rather than creating a copy) 
df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'}, inplace=True)

最简代码示例

df = pd.DataFrame('x', index=range(3), columns=list('abcde'))
df

   a  b  c  d  e
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

以下方法都可以正常工作并产生相同的输出结果:
df2 = df.rename({'a': 'X', 'b': 'Y'}, axis=1)
df2 = df.rename({'a': 'X', 'b': 'Y'}, axis='columns')
df2 = df.rename(columns={'a': 'X', 'b': 'Y'}) 

df2

   X  Y  c  d  e
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

记得将结果重新赋值,因为修改不是就地进行的。或者可以指定 inplace=True
df.rename({'a': 'X', 'b': 'Y'}, axis=1, inplace=True)
df

   X  Y  c  d  e
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x
 

您可以使用errors='raise'来指定,如果指定了无效的要重命名的列,则会引发错误。

重新分配列标题

使用df.set_axis()axis=1

df2 = df.set_axis(['V', 'W', 'X', 'Y', 'Z'], axis=1)
df2

   V  W  X  Y  Z
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

标题可以直接分配:
df.columns = ['V', 'W', 'X', 'Y', 'Z']
df

   V  W  X  Y  Z
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

3
当我对一个有六列的数据框(dataframe)进行操作时(输入dataframe并按下回车键),它的简略表示为:code <class 'pandas.core.frame.DataFrame'> Int64Index: 1000 entries, 0 to 999 Data columns: BodyMarkdown 1000 non-null。使用 code 可以正常工作,但是当我使用 dataframe.head() 函数时,旧列名会重新出现。 - darKoram
15
当我使用这个答案中的第二段代码时,出现了可怕的SettingWithCopyWarning:警告。 - Monica Heddneck
31
第一种解决方法:df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})更改了显示的名称,但没有更改底层数据结构中的元素。因此,如果您尝试df['newName1'],将会出现一个错误。inplace=True是必要的,以避免这种问题。 - irritable_phd_syndrome
1
为避免 "SettingWithCopyWarning",请执行以下代码: df = df.copy().rename(columns={'old':'new_name'})。这意味着首先要复制整个数据框,进行重命名,然后将其分配,完全覆盖原始数据框。 - gseattle
"inplace" 可能会被弃用:https://www.dataschool.io/future-of-pandas/#inplace - PatrickT
显示剩余8条评论

2528

只需将其分配给.columns属性:

>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df
   $a  $b
0   1  10
1   2  20

>>> df.columns = ['a', 'b']
>>> df
   a   b
0  1  10
1  2  20

391
可以更改单个列标题的名称吗? - ericmjl
149
假设您想更改df的第一个变量的名称。那么您可以这样做: new_columns = df.columns.values; new_columns[0] = 'XX'; df.columns = new_columns - cd98
72
看起来你可以简单地执行 df.columns.values[0]='XX'。 - RAY
32
开玩笑的,@RAY - 别那样做。看起来这是一个独立于存储列名的索引生成的列表。会很好地破坏你的数据框的列命名... - Mitch Flax
557
@ericmjl,是的 df.rename(columns={'$b':'B'}, inplace=True)。该代码用于将 Pandas 数据框 df 中名为 "$b" 的列重命名为 "B",并直接在原数据框上进行修改。 - nachocab
显示剩余9条评论

515

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)

70
这一行代码拯救了我的一天:df.rename(columns=lambda x: x.lstrip(), inplace=True) - root-11
3
与@root-11类似,在我的情况下,IPython控制台输出中没有打印出一个符号点,因此我需要删除的不仅仅是空格(strip),所以写成:t.columns = t.columns.str.replace(r'[^\x00-\x7F]+','') - Nate Anderson
18
df.rename(columns=lambda x: x.replace(' ', '_'), inplace=True) 是一条好的命令,它使我们能够写 df.Column_1_Name 而不是写 df.loc[:, 'Column 1 Name'] - Little Bobby Tables
这不是首选解决方案吗?只有这样才能处理大量的特征名称,例如通过删除/替换标签中的空格来允许点符号表示法,正如@LittleBobbyTables所演示的那样。 - error404
@root-11 我认为你甚至可以这样做:df.rename(columns=str.lstrip) - Ian Liu Rodrigues
@IanLiuRodrigues - 自 2013 年以来发生了很多事情 :-) - root-11

271

正如在处理文本数据中所记录的:

df.columns = df.columns.str.replace('$', '')

199

Pandas 0.21+ 答案

在版本0.21中,列重命名有了一些重大更新。

  • rename方法添加了axis参数,可以设置为columns1。此更新使该方法与pandas API的其余部分匹配。它仍然具有indexcolumns参数,但您不再被强制使用它们。
  • set_axis方法inplace设置为False,使您能够使用列表重命名所有索引或列标签。

Pandas 0.21+示例

构造示例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

使用renameaxis='columns'axis=1

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)

两者都会导致以下结果:
   a  b  c  d   e
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)

使用列表和inplace=Falseset_axis方法

您可以向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']

直接这样分配列没有问题,是一个完全可行的解决方案。

使用set_axis的优点是它可以作为方法链的一部分使用,并且它返回DataFrame的新副本。如果不使用它,则必须将链的中间步骤存储到另一个变量中,然后重新分配列。

# 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()

1
感谢您提供的 Pandas 0.21+ answer - 不知何故,我在“新功能”部分错过了那一部分... - MaxU - stand with Ukraine
1
该解决方案似乎不适用于 Pandas 3.6: df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis='columns')。 出现了意外的关键字参数“axis”。 - Arthur D. Howland
3
df.columns = ['a', 'b', 'c', 'd', 'e'] 这段代码似乎在版本0.22中无法使用了,我收到了一个警告,提示“Pandas不允许通过新属性名称创建列”。如果我所有的列都叫同一个名字,该怎么重命名呢? - Nabla
有没有一种方法可以重命名一个、多个或所有的列,如果你不知道列名字,只知道它们的索引?谢谢! - tommy.carstensen
这是一个非常有帮助的评论。例如,lambda函数回答了我的以下问题:(df .groupby(['page',pd.Grouper(key='date',freq='MS')])['clicks'].sum() .unstack(1) .rename(lambda x: x.strftime("%Y-%m"), axis='columns') ) - measureallthethings

160

如果您只想在所有列名称中删除美元符号,您可以这样做:

df = df.rename(columns=lambda x: x.replace('$', ''))

或者

df.rename(columns=lambda x: x.replace('$', ''), inplace=True)

3
这个不仅可以帮助 OP 的情况,还适用于通用需求。例如:通过分隔符拆分列名并使用其中一部分。 - Deepak

141

Pandas中重命名列是一项简单的任务。

df.rename(columns={'$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}, inplace=True)

2
我会升级这个,因为它是自然支持的。 - lkahtz
1
比批准的解决方案好得多。 - slisnychyi
2
这里的 columns 参数也可以是一个函数。因此,如果您想从每个名称中删除第一个字符,可以执行 df.rename(columns=lambda name: name[1:], inplace=True)参考)。 - aschmied
1
这非常自然。您可以对任意列执行此操作。这应该是一个被接受的答案。 - Shaida Muhammad
使用以下方法为未标记的列添加标签:df.rename(columns={0: "x", 1: "y", 2: "z"}) - ZakS

95
df.columns = ['a', 'b', 'c', 'd', 'e']

它将按照您提供的顺序,使用您提供的名称替换现有名称。


5
不要修改 df.columns.values,这是错误的。https://dev59.com/KlgQ5IYBdhLWcg3wGgP0 - llllllllll

82

使用:

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,使其符合您的要求。当您仅需更改少量列名以纠正拼写错误、重音、删除特殊字符等情况时,它非常有效。


3
我喜欢这种方法,但我认为 df.columns = ['a', 'b', 'c', 'd', 'e'] 更简单。 - Christopher Pearson
3
我喜欢这种压缩旧名称和新名称的方法。我们可以使用 df.columns.values 来获取旧名称。 - bkowshik
1
我展示表格视图并将列复制到old_names。 我将要求数组复制到new_names。 然后使用dict(zip(old_names, new_names))。 非常优雅的解决方案。 - mythicalcoder
我经常使用类似以下的列表子集:myList = list(df) myList[10:20],等等 - 所以这非常完美。 - Tim Gottgetreu
1
最好按照@bkowshik的建议使用旧名称,然后进行编辑和重新插入,即namez = df.columns.values接着进行一些编辑,然后df.columns = namez - pauljohn32

44

一行或管道解决方案

我将关注两件事:

  1. OP明确说明:

    我已经将编辑后的列名存储在一个列表中,但我不知道如何替换列名。

    我不想解决如何替换'$'或去掉每个列头的第一个字符的问题。 OP已经完成了这一步。 我想专注于根据替换列名的列表替换现有的columns对象。

  2. df.columns = new,其中new是新列名列表,这是最简单的方法。 这种方法的缺点是它需要编辑现有数据框的columns属性,并且它不能直接完成。 我将展示一些通过流水线执行此操作的方法,而无需编辑现有的数据框。


设置1
为了关注使用预先存在的列表重命名或替换列名的必要性,我将创建一个新的示例数据框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

解决方案1
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

然而,您可以轻松创建该字典并将其包含在对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

解决方案 2
使用pd.concat函数和keys参数

首先,注意当我们尝试使用解决方案 1 时会发生什么:

df.rename(columns=dict(zip(df, new)))

   y765  y765  z432
0     1     3     5
1     2     4     6

我们没有将“新”列表映射为列名。结果,我们不得不重复使用“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

解决方案三
重构。只有在所有列使用相同的 dtype 时才应该使用此方法。否则,您将得到所有列的 dtypeobject,并且将它们转换回来需要更多的字典工作。

单一 dtype

pd.DataFrame(df.values, df.index, new)

   x098  y765  z432
0     1     3     5
1     2     4     6

混合数据类型

pd.DataFrame(df.values, df.index, new).astype(dict(zip(new, df.dtypes)))

   x098  y765  z432
0     1     3     5
1     2     4     6

解决方案4
这是一个使用transposeset_index的花哨技巧。 pd.DataFrame.set_index允许我们在内联中设置索引,但没有相应的set_columns。所以我们可以进行转置,然后set_index,再次转置回来。但是,与解决方案3相同的单个dtype与混合dtype的注意事项也适用于此处。

单个dtype

df.T.set_index(np.asarray(new)).T

   x098  y765  z432
0     1     3     5
1     2     4     6

混合数据类型

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

解决方案5
使用pd.DataFrame.rename中的lambda循环遍历new的每个元素。
在此解决方案中,我们传递一个lambda,它接受x但忽略它。它还接受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之间添加一个*,就可以保护我的y变量。虽然在这种情况下我不认为它需要保护,但还是值得一提。

df.rename(columns=lambda x, *, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

2
也许我们可以添加 df.rename(lambda x : x.lstrip('$'),axis=1) - BENY
1
嗨@piRSquared,您能否详细说明pandas在解决方案5中如何使用lambda函数?当您说“x”被忽略时,我不太明白您的意思。 - Josmoor98

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接