首页 文章

重命名pandas中的列

提问于
浏览
1208

我有一个使用pandas和列标签的DataFrame,我需要编辑它来替换原始列标签 .

我想在原始列名称为的DataFrame A 中更改列名:

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

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

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

28 回答

  • 313

    如果你不想要行名 df.columns = ['a', 'b',index=False]

  • 134

    我认为这种方法很有用:

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

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

  • 2

    我知道这个问题和答案已被咀嚼致死 . 但我提到它是我遇到的一个问题的灵感来源 . 我能够使用来自不同答案的点点滴滴解决它,从而在任何人需要时提供我的回复 .

    我的方法是通用的,您可以通过逗号分隔 delimiters= 变量和将来证明它来添加其他分隔符 .

    Working Code:

    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 ]
    

    Output:

    >>> 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
    
  • 30

    列名称与系列名称

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

    数据帧是一组系列 .

    系列又是 numpy.array 的延伸

    numpy.array s有一个属性 .name

    这是该系列的名称 . 很少有熊猫尊重这个属性,但它在某些地方徘徊,可以用来破解一些熊猫行为 .

    命名列的列表

    这里有很多答案说 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 属性有时会持续存在 . 如果设置 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']]
    
  • 16

    我们可以替换原始列标签的另一种方法是从原始列标签中剥离不需要的字符(此处为“$”) .

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

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

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

    strip Python中的方法从字符串的开头和结尾剥离给定的字符 . )

  • 2046

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

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

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

    df.columns = df.columns.str.replace('$','')
    
  • 119
    Renaming columns while reading the Dataframe: 
    
    >>> 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
    
  • 15

    由于您只想删除所有列名中的$符号,您可以这样做:

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

    要么

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

    如果你不得不处理由提供系统命名的大量列的控制,我想出了以下方法,即一次性方法和特定替换的组合 .

    我首先使用正则表达式从数据框列名创建一个字典,以便抛弃某些字典列名的附录,然后我在字典中添加特定的替换,以便在接收数据库中稍后按预期命名核心列 .

    然后将其一次性应用于数据帧 .

    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)
    
  • 5

    熊猫0.21答案

    版本0.21中的列重命名有一些重要更新 .

    • rename method添加了 axis 参数,该参数可以设置为 columns1 . 此更新使此方法与其余的pandas API匹配 . 它仍然具有 indexcolumns 参数,但您不再被迫使用它们 .

    • set_axis methodinplace 设置为 False 使您可以使用列表重命名所有索引或列标签 .

    熊猫的例子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
    

    使用axis ='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)
    

    将set_axis与list和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']?

    像这样直接分配列没有任何问题 . 这是一个非常好的解决方案 .

    使用 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()
    
  • 32

    如果你有数据帧,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具有执行时间最快的功能 - 尽管这些功能如此之快,我们正在比较所有答案的.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)')
    
  • 115
    df.columns = ['a', 'b', 'c', 'd', 'e']
    

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

  • 55

    请注意,这些方法不适用于MultiIndex . 对于MultiIndex,您需要执行以下操作:

    >>> 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
    
  • 1249
    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 . 当您只需要重命名几列以纠正错误拼写,重音,删除特殊字符等时,效果很好 .

  • 9

    您可以使用str.slice

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

    一条线或管道解决方案

    我会专注于两件事:

    • OP明确指出

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

    我不想解决如何替换 '$' 或从每个列 Headers 中删除第一个字符的问题 . OP已经完成了这一步 . 相反,我想专注于使用给定替换列名列表的新对象替换现有的 columns 对象 .

    • df.columns = new 其中 new 是新列名称的列表,就像它获得的一样简单 . 这种方法的缺点是它需要编辑现有数据框的 columns 属性,并且它没有显示通过流水线操作执行此操作而无需编辑现有数据框的几种方法 .

    Setup 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
    

    Solution 1
    pd.DataFrame.rename

    已经说过 if 你有一个将旧列名称映射到新列名的字典,你可以使用 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
    

    如果原始列名称是唯一的,则此方法很有用 . 但如果他们不是,那么这就会崩溃 .


    Setup 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
    

    Solution 2
    pd.concat使用 keys 参数

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

    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
    

    Solution 3
    重建 . 仅当您对所有列都有一个 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
    

    Solution 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
    

    混合 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
    

    Solution 5
    在_179107中使用 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
    
  • 9

    DataFrame - df.rename()将起作用 .

    df.rename(columns = {'Old Name':'New Name'})
    

    df是您拥有的DataFrame,旧名称是您要更改的列名,然后New Name是您更改为的新名称 . 这种DataFrame内置方法使事情变得更加容易 .

  • 20

    The rename dataframe columns and replace format

    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(' ', '_')
    
  • 7

    试试这个 . 这个对我有用

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

    使用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)
    
  • 13

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

    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
    
  • 4

    这是一个漂亮的小功能,我喜欢用它来减少打字:

    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
    

    以下是它的工作原理示例:

    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')
    
  • 13
    df = df.rename(columns=lambda n: n.replace('$', ''))
    

    是一种解决这个问题的功能性方法

  • 2

    真正的简单只是使用

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

    它将按照您放置它们的顺序分配列名称

  • 7

    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)
    
  • 5
    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
       a  b  c  d  e
    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
       a  b  c  d  e
    0  1  1  1  1  1
    

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

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

相关问题