关于python:重命名panda中的列

Renaming columns in pandas

我有一个使用panda和列标签的数据帧,我需要编辑它们来替换原始的列标签。

我想更改数据帧A中的列名称,其中原始列名称为:

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

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

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


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

1
2
3
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)


rename方法可以采用函数,例如:

1
2
3
4
5
6
7
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)


如http://pandas.pydata.org/pandas-docs/stable/text.html所述:

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


熊猫0.21+答案

在0.21版本中,对列重命名进行了一些重要的更新。

  • rename方法增加了axis参数,可以设置为columns1。此更新使此方法与熊猫API的其余部分相匹配。它仍然有indexcolumns参数,但您不再被迫使用它们。
  • inplace设置为Falseset_axis方法允许您用列表重命名所有索引或列标签。

熊猫的例子0.21+

构造示例数据帧:

1
2
3
4
5
6
7
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

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

1
df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis=1)

两者都会导致以下结果:

1
2
3
   a  b  c  d   e
0  1  3  5  7   9
1  2  4  6  8  10

仍然可以使用旧方法签名:

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

rename函数还接受将应用于每个列名的函数。

1
df.rename(lambda x: x[1:], axis='columns')

1
df.rename(lambda x: x[1:], axis=1)

使用带列表的set_axisinplace=False

您可以向set_axis方法提供一个长度等于列数(或索引)的列表。目前,inplace默认为True,但inplace将在未来版本中默认为False

1
df.set_axis(['a', 'b', 'c', 'd', 'e'], axis='columns', inplace=False)

1
df.set_axis(['a', 'b', 'c', 'd', 'e'], axis=1, inplace=False)

为什么不使用df.columns = ['a', 'b', 'c', 'd', 'e']

直接这样分配列没有任何错误。这是一个完美的解决方案。

使用set_axis的优点是,它可以作为方法链的一部分使用,并返回数据帧的新副本。如果没有它,在重新分配列之前,必须将链的中间步骤存储到另一个变量。

1
2
3
4
5
6
7
8
9
10
11
# 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()


因为您只想删除$sign-in所有的列名,所以您可以这样做:

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

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


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

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


1
2
3
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。当您只需要重命名几列以更正拼写错误、重音符号、删除特殊字符等时,效果非常好。


我认为这种方法很有用:

1
df.rename(columns={"old_column_name1":"new_column_name1","old_column_name2":"new_column_name2"})

此方法允许您单独更改列名。


列名与序列名

我想解释一下幕后发生的事情。

数据帧是一组序列。

系列依次是numpy.array的扩展

numpy.arrays拥有.name的财产。

这是系列的名称。熊猫很少尊重这一属性,但它会在某些地方逗留,并可以用来攻击一些熊猫的行为。

命名列列表

这里的很多答案都是关于df.columns属性是list,而实际上它是Series。这意味着它有一个.name属性。

如果您决定填写列的名称Series,就会发生这种情况:

1
2
3
4
5
6
7
8
9
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属性有时会继续存在。如果设置df.columns = ['one', 'two'],那么df.one.name将是'one'

如果你设置了df.one.name = 'three',那么df.columns仍然会给你['one', 'two']df.one.name会给你'three'

但是

pd.DataFrame(df.one)将返回

1
2
3
4
    three
0       1
1       2
2       3

因为熊猫会重复使用已经定义的Series中的.name

多级列名

熊猫有多层次列名的方法。这里面没有太多的魔法,但我也想在我的答案中包含这一点,因为我没有看到任何人在这里发现这一点。

1
2
3
4
5
    |one            |
    |one      |two  |
0   |  4      |  1  |
1   |  5      |  2  |
2   |  6      |  3  |

这很容易通过将列设置为列表来实现,如下所示:

1
df.columns = [['one', 'one'], ['one', 'two']]

单线或管道解决方案

我将关注两件事:

  • OP明确说明


    I have the edited column names stored it in a list, but I don't know how to replace the column names.

    我不想解决如何替换'$'或去掉每个列标题的第一个字符的问题。OP已经完成了这个步骤。相反,我想重点将现有的columns对象替换为给定替换列名称列表的新对象。

  • df.columns = new,其中new是新列的列表,名称尽可能简单。这种方法的缺点是,它需要编辑现有数据帧的columns属性,而不是内联完成。我将展示一些通过管道系统执行此操作的方法,而不编辑现有的数据帧。

  • 设置1为了关注用预先存在的列表重命名替换列名的需要,我将创建一个新的示例数据框df,其中包含初始列名和不相关的新列名。

    1
    2
    3
    4
    5
    6
    7
    8
    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

    解决方案1pd.DataFrame.rename

    已经说过,如果您有一个字典将旧的列名映射到新的列名,那么您可以使用pd.DataFrame.rename

    1
    2
    3
    4
    5
    6
    d = {'Jack': 'x098', 'Mahesh': 'y765', 'Xin': 'z432'}
    df.rename(columns=d)

       x098  y765  z432
    0     1     3     5
    1     2     4     6

    但是,您可以轻松地创建该字典并将其包含在对rename的调用中。下面利用这样一个事实:当对df进行迭代时,我们对每个列名进行迭代。

    1
    2
    3
    4
    5
    6
    # 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非唯一列

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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使用keys参数的pd.concat

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

    1
    2
    3
    4
    5
    df.rename(columns=dict(zip(df, new)))

       y765  y765  z432
    0     1     3     5
    1     2     4     6

    我们没有将new列表映射为列名称。我们最后重复了y765。相反,我们可以在遍历df的列时使用pd.concat函数的keys参数。

    1
    2
    3
    4
    5
    pd.concat([c for _, c in df.items()], axis=1, keys=new)

       x098  y765  z432
    0     1     3     5
    1     2     4     6

    解决方案3重建。只有在所有列都有单个dtype时,才应使用此选项。否则,您将最终得到所有列的dtypeobject,而将它们转换回来需要更多的字典工作。

    单根dtype

    1
    2
    3
    4
    5
    pd.DataFrame(df.values, df.index, new)

       x098  y765  z432
    0     1     3     5
    1     2     4     6

    混合dtype

    1
    2
    3
    4
    5
    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,然后转座子回来。然而,同样的单一dtype和混合dtype的解决方案3的警告也适用于这里。

    单根dtype

    1
    2
    3
    4
    5
    df.T.set_index(np.asarray(new)).T

       x098  y765  z432
    0     1     3     5
    1     2     4     6

    混合dtype

    1
    2
    3
    4
    5
    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中使用循环通过new的每个元素的lambda。在这个解决方案中,我们传递一个lambda,该lambda接受x,但随后忽略它。它也需要一个y,但并不期望如此。相反,一个迭代器作为一个默认值给出,然后我可以使用它一次循环一个迭代器,而不考虑x的值是什么。

    1
    2
    3
    4
    5
    df.rename(columns=lambda x, y=iter(new): next(y))

       x098  y765  z432
    0     1     3     5
    1     2     4     6

    正如sopython聊天室的人向我指出的,如果我在xy之间加上一个*,我就可以保护我的y变量。不过,在这种情况下,我认为它不需要保护。这仍然值得一提。

    1
    2
    3
    4
    5
    df.rename(columns=lambda x, *, y=iter(new): next(y))

       x098  y765  z432
    0     1     3     5
    1     2     4     6


    1
    df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})

    如果新列列表与现有列的顺序相同,则分配很简单:

    1
    2
    3
    4
    5
    new_cols = ['a', 'b', 'c', 'd', 'e']
    df.columns = new_cols
    >>> df
       a  b  c  d  e
    0  1  1  1  1  1

    如果有一个字典将旧列名键入新列名,则可以执行以下操作:

    1
    2
    3
    4
    5
    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
       a  b  c  d  e
    0  1  1  1  1  1

    如果没有列表或字典映射,则可以通过列表理解来删除前导的$符号:

    1
    df.columns = [col[1:] if col[0] == '$' else col for col in df]


    df = df.rename(columns=lambda n: n.replace('$', ''))是解决这个问题的有效方法


    如果有了数据帧,df.columns会将所有内容转储到一个可以操作的列表中,然后作为列的名称重新分配到数据帧中…

    1
    2
    3
    4
    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的函数执行时间最快-虽然这些函数执行速度非常快,但我们比较了所有答案的0.000和0.001秒取整。道德:我上面的回答可能不是最好的方式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    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)')


    1
    df.rename(index=str,columns={'A':'a','B':'b'})

    https://pandas.pydata.org/pandas-docs/stable/generated/pandas.dataframe.rename.html


    另一种替换原始列标签的方法是从原始列标签中除去不需要的字符(这里是"$")。

    这可以通过在df.columns上运行for循环并将剥离的列附加到df.columns来完成。

    相反,我们可以使用下面的列表理解在一个语句中巧妙地做到这一点:

    1
    df.columns = [col.strip('$') for col in df.columns]

    (python中的strip方法从字符串的开头和结尾剥离给定字符。)


    我知道这个问题和答案已经被反复考虑过了。但我提到它是为了启发我遇到的一个问题。我能够用不同答案的零碎部分来解决这个问题,因此在任何人需要的时候提供我的响应。

    我的方法是通用的,您可以通过逗号分隔delimiters=变量和将来的证明添加额外的定界符。

    工作代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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 ]

    输出:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> df
       $a  $b  $c  $d  $e
    0   1   3   5   7   9
    1   2   4   6   8  10

    >>> df
       a  b  c  d   e
    0  1  3  5  7   9
    1  2  4  6  8  10

    您可以使用str.slice来实现:

    1
    df.columns = df.columns.str.slice(1)

    真正的简单使用

    1
    df.columns = ['Name1', 'Name2', 'Name3'...]

    它将按您输入的顺序分配列名称


    注意,这些方法不适用于多索引。对于多索引,需要执行以下操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    >>> df = pd.DataFrame({('$a','$x'):[1,2], ('$b','$y'): [3,4], ('e','f'):[5,6]})
    >>> df
       $a $b  e
       $x $y  f
    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
       a  b  e
       x  y  f
    0  1  3  5
    1  2  4  6

    另一个选项是使用正则表达式重命名:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import pandas as pd
    import re

    df = pd.DataFrame({'$a':[1,2], '$b':[3,4], '$c':[5,6]})

    df = df.rename(columns=lambda x: re.sub('\$','',x))
    >>> df
       a  b  c
    0  1  3  5
    1  2  4  6

    重命名数据帧列并替换格式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import pandas as pd

    data = {'year':[2015,2011,2007,2003,1999,1996,1992,1987,1983,1979,1975],
            'team':['Australia','India','Australia','Australia','Australia','Sri Lanka','Pakistan','Australia','India','West Indies','West Indies'],
            }
    df = pd.DataFrame(data)

    #Rename Columns
    df.rename(columns={'year':'Years of Win','team':'Winning Team'}, inplace=True)

    #Replace format
    df = df.columns.str.replace(' ', '_')

    读取数据帧时重命名列:

    1
    2
    3
    4
    5
    6
    >>> df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1]}).rename(columns =
             {'$a' : 'a','$b':'b','$c':'c'})

    Out[1]:
       a  b  c
    0  1  1  1

    导入有助于创建数据帧的库:

    1
    2
    import pandas as pd
    import numpy as np

    创建数据帧:

    1
    df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])

    重命名数据帧:

    1
    df.rename(columns={'a':'x', 'b':'y', 'c':'z'}, index=str)

    df.columns现在应该有不同的值


    我看到3个简单的方法

    df.columns

    输出:'$A'、'$B'、'$C'、'$D'、'$E']

    1。

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

    2。

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

    三。

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


    如果必须处理由不受控制的提供系统命名的列的负载,那么我提出了以下方法,它是通用方法和特定替换的组合。

    我首先使用regex表达式从数据帧列名创建字典,以便丢弃列名的某些附录。然后,我向字典添加特定的替换,以命名核心列,正如后面在接收数据库中所预期的那样。

    然后一次应用于数据帧。

    1
    2
    3
    4
    5
    6
    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]


    试试这个。它对我有用

    1
    df.rename(index=str, columns={"$a":"a","$b":"b","$c" :"c","$d" :"d","$e" :"e"})

    这里有一个我喜欢用来减少打字的漂亮的小功能:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    def rename(data, oldnames, newname):
        if type(oldnames) == str: #input can be a string or list of strings
            oldnames = [oldnames] #when renaming multiple columns
            newname = [newname] #make sure you pass the corresponding list of new names
        i = 0
        for name in oldnames:
            oldvar = [c for c in data.columns if name in c]
            if len(oldvar) == 0:
                raise ValueError("Sorry, couldn't find that column in the dataset")
            if len(oldvar) > 1: #doesn't have to be an exact match
                print("Found multiple columns that matched" + str(name) +" :")
                for c in oldvar:
                    print(str(oldvar.index(c)) +":" + str(c))
                ind = input('please enter the index of the column you would like to rename: ')
                oldvar = oldvar[int(ind)]
            if len(oldvar) == 1:
                oldvar = oldvar[0]
            data = data.rename(columns = {oldvar : newname[i]})
            i += 1
        return data

    下面是一个如何工作的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    In [2]: df = pd.DataFrame(np.random.randint(0,10,size=(10, 4)), columns=['col1','col2','omg','idk'])
    #first list = existing variables
    #second list = new names for those variables
    In [3]: df = rename(df, ['col','omg'],['first','ohmy'])
    Found multiple columns that matched col :
    0: col1
    1: col2

    please enter the index of the column you would like to rename: 0

    In [4]: df.columns
    Out[5]: Index(['first', 'col2', 'ohmy', 'idk'], dtype='object')

    1
    2
    3
    4
    import pandas as pd
    df.columns = [['$a', '$b', '$c', '$d', '$e']]
    df.rename(columns = {'$a':'a','$b':'b','$c':'c','$d':'d','$e':'e'})
    df.head()


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import pandas as pd

    data = {'year':[2015,2011,2007,2003,1999,1996,1992,1987,1983,1979,1975],
            'team':['Australia','India','Australia','Australia','Australia','Sri Lanka','Pakistan','Australia','India','West Indies','West Indies'],
            }
    df = pd.DataFrame(data)

    #Rename Columns
    df.rename(columns={'year':'Years of Win','team':'Winning Team'}, inplace=True)

    #Replace format
    df.columns = df.columns.str.replace(' ', '_')

    假设您可以使用正则表达式。此解决方案消除了使用regex进行手动编码的需要。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import pandas as pd
    import re

    srch=re.compile(r"\w+")

    data=pd.read_csv("CSV_FILE.csv")
    cols=data.columns
    new_cols=list(map(lambda v:v.group(),(list(map(srch.search,cols)))))
    data.columns=new_cols