Pandas的DataFrame - 重命名多个相同名称的列

34 投票
14 回答
60107 浏览
提问于 2025-04-18 12:51

我在一个数据表(df)里有好几个名字一样的列。我想给它们改名字,但问题是用 df.rename 这个方法改名字的时候,所有的列都会被改成一样的名字。我该怎么把下面这些名字改成 blah1、blah4、blah5 呢?

df = pd.DataFrame(np.arange(2*5).reshape(2,5))
df.columns = ['blah','blah2','blah3','blah','blah']
df

#     blah  blah2  blah3  blah  blah
# 0   0     1      2      3     4
# 1   5     6      7      8     9

这是使用 df.rename 方法时发生的情况:

df.rename(columns={'blah':'blah1'})

#     blah1  blah2  blah3  blah1  blah1
# 0   0      1      2      3      4
# 1   5      6      7      8      9

14 个回答

4

我刚写了这段代码,它使用了一种叫做列表推导的方法来更新所有重复的名字。

df.columns = [x[1] if x[1] not in df.columns[:x[0]] else f"{x[1]}_{list(df.columns[:x[0]]).count(x[1])}" for x in enumerate(df.columns)]
4

你可以直接给列赋值:

In [12]:

df.columns = ['blah','blah2','blah3','blah4','blah5']
df
Out[12]:
   blah  blah2  blah3  blah4  blah5
0     0      1      2      3      4
1     5      6      7      8      9

[2 rows x 5 columns]

如果你想动态地重命名重复的列,可以参考下面的做法(这段代码来自答案2:Python列表中重复项的索引):

In [25]:

import collections
dups = collections.defaultdict(list)
dup_indices=[]
col_list=list(df.columns)
for i, e in enumerate(list(df.columns)):
  dups[e].append(i)
for k, v in sorted(dups.items()):
  if len(v) >= 2:
    dup_indices = v

for i in dup_indices:
    col_list[i] = col_list[i] + ' ' + str(i)
col_list
Out[25]:
['blah 0', 'blah2', 'blah3', 'blah 3', 'blah 4']

然后你可以用这个方法重新赋值,你也可以写一个函数来生成一个在重命名之前不重复的唯一名称。

13

你可以使用这个:

def df_column_uniquify(df):
    df_columns = df.columns
    new_columns = []
    for item in df_columns:
        counter = 0
        newitem = item
        while newitem in new_columns:
            counter += 1
            newitem = "{}_{}".format(item, counter)
        new_columns.append(newitem)
    df.columns = new_columns
    return df

然后

import numpy as np
import pandas as pd

df=pd.DataFrame(np.arange(2*5).reshape(2,5))
df.columns=['blah','blah2','blah3','blah','blah']

这样df

   blah  blah2  blah3   blah   blah
0     0      1      2      3      4
1     5      6      7      8      9

接着

df = df_column_uniquify(df)

这样df

   blah  blah2  blah3  blah_1  blah_2
0     0      1      2       3       4
1     5      6      7       8       9
39

从Pandas 0.19.0开始,pd.read_csv()对重复列名的支持得到了改善

所以我们可以尝试使用内部方法:

In [137]: pd.io.parsers.ParserBase({'names':df.columns})._maybe_dedup_names(df.columns)
Out[137]: ['blah', 'blah2', 'blah3', 'blah.1', 'blah.2']

自Pandas 1.3.0起:

pd.io.parsers.base_parser.ParserBase({'names':df.columns, 'usecols':None})._maybe_dedup_names(df.columns)

这是一个“魔法”函数:

def _maybe_dedup_names(self, names):
    # see gh-7160 and gh-9424: this helps to provide
    # immediate alleviation of the duplicate names
    # issue and appears to be satisfactory to users,
    # but ultimately, not needing to butcher the names
    # would be nice!
    if self.mangle_dupe_cols:
        names = list(names)  # so we can index
        counts = {}

        for i, col in enumerate(names):
            cur_count = counts.get(col, 0)

            if cur_count > 0:
                names[i] = '%s.%d' % (col, cur_count)

            counts[col] = cur_count + 1

    return names
36

我想在Pandas里找到一个解决方案,而不是用一般的Python方法。列的get_loc()函数会返回一个带掩码的数组,如果发现重复项,它会用'True'标记出重复项的位置。然后我可以用这个掩码来给这些位置赋新值。在我的情况下,我事先知道会有多少个重复项,以及我想给它们赋什么值,但看起来df.columns.get_duplicates()会返回所有重复项的列表,如果你需要更通用的去重操作,可以结合这个列表和get_loc()来使用。

'''截至2020年9月更新'''

cols=pd.Series(df.columns)
for dup in df.columns[df.columns.duplicated(keep=False)]: 
    cols[df.columns.get_loc(dup)] = ([dup + '.' + str(d_idx) 
                                     if d_idx != 0 
                                     else dup 
                                     for d_idx in range(df.columns.get_loc(dup).sum())]
                                    )
df.columns=cols

    blah    blah2   blah3   blah.1  blah.2
 0     0        1       2        3       4
 1     5        6       7        8       9

更好的新方法(更新于2019年12月3日)

下面的代码比上面的代码更好。是从下面的另一个答案中复制过来的(@SatishSK):

#sample df with duplicate blah column
df=pd.DataFrame(np.arange(2*5).reshape(2,5))
df.columns=['blah','blah2','blah3','blah','blah']
df

# you just need the following 4 lines to rename duplicates
# df is the dataframe that you want to rename duplicated columns

cols=pd.Series(df.columns)

for dup in cols[cols.duplicated()].unique(): 
    cols[cols[cols == dup].index.values.tolist()] = [dup + '.' + str(i) if i != 0 else dup for i in range(sum(cols == dup))]

# rename the columns with the cols list.
df.columns=cols

df

输出:

    blah    blah2   blah3   blah.1  blah.2
0   0   1   2   3   4
1   5   6   7   8   9

撰写回答