Panda的DataFrame - 重命名多个具有相同名称的列

时间:2014-07-10 19:46:13

标签: python pandas

我在df中有几个相同的列。需要重命名它们。通常的重命名重命名全部 无论如何,我可以将下面的blah(s)重命名为blah1,blah4,blah5?

    In [6]:

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


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

在[7]中:

df.rename(columns = {'blah':'blah1'})
Out[7]:
        blah1   blah2   blah3   blah1   blah1
        0    0   1   2   3   4
        1    5   6   7   8   9

11 个答案:

答案 0 :(得分:13)

我希望在Pandas中找到一个解决方案而不是一般的Python解决方案。 如果列的get_loc()函数找到重复项,并且“True”值指向找到重复项的位置,则它返回一个屏蔽数组。然后我使用掩码为这些位置分配新值。在我的情况下,我提前知道我将获得多少重复以及我将要分配给他们但是看起来df.columns.get_duplicates()会返回所有重复的列表然后你可以如果您需要更通用的重复除草操作,请将该列表与get_loc()结合使用

cols=pd.Series(df.columns)
for dup in df.columns.get_duplicates(): 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

答案 1 :(得分:11)

Starting with Pandas 0.19.0 pd.read_csv() has improved support for duplicate column names

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

GetData2

这是“魔术”功能:

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

答案 2 :(得分:7)

你可以用这个:

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

答案 3 :(得分:3)


duplicated_idx = dataset.columns.duplicated()

duplicated = dataset.columns[duplicated_idx].unique()



rename_cols = []

i = 1
for col in dataset.columns:
    if col in duplicated:
        rename_cols.extend([col + '_' + str(i)])
    else:
        rename_cols.extend([col])

dataset.columns = rename_cols

答案 4 :(得分:2)

您可以直接指定列:

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:Index of duplicates items in a python list):

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']

然后您可以使用它来分配回来,您还可以使用一个函数来生成在重命名之前列中不存在的唯一名称。

答案 5 :(得分:1)

这是一种适用于多索引的解决方案

# Take a df and rename duplicate columns by appending number suffixes
def rename_duplicates(df):
    import copy
    new_columns = df.columns.values
    suffix = {key: 2 for key in set(new_columns)}
    dup = pd.Series(new_columns).duplicated()

    if type(df.columns) == pd.core.indexes.multi.MultiIndex:
        # Need to be mutable, make it list instead of tuples
        for i in range(len(new_columns)):
            new_columns[i] = list(new_columns[i])
        for ix, item in enumerate(new_columns):
            item_orig = copy.copy(item)
            if dup[ix]:
                for level in range(len(new_columns[ix])):
                    new_columns[ix][level] = new_columns[ix][level] + f"_{suffix[tuple(item_orig)]}"
                suffix[tuple(item_orig)] += 1

        for i in range(len(new_columns)):
            new_columns[i] = tuple(new_columns[i])

        df.columns = pd.MultiIndex.from_tuples(new_columns)
    # Not a MultiIndex
    else:
        for ix, item in enumerate(new_columns):
            if dup[ix]:
                new_columns[ix] = item + f"_{suffix[item]}"
                suffix[item] += 1
        df.columns = new_columns

答案 6 :(得分:0)

由于接受的答案(由Lamakaha提出)不适用于最新版本的熊猫,并且由于其他建议看起来有些笨拙,因此我制定了自己的解决方案:

def dedupIndex(idx, fmt=None, ignoreFirst=True):
    # fmt:          A string format that receives two arguments: 
    #               name and a counter. By default: fmt='%s.%03d'
    # ignoreFirst:  Disable/enable postfixing of first element.
    idx = pd.Series(idx)
    duplicates = idx[idx.duplicated()].unique()
    fmt = '%s.%03d' if fmt is None else fmt
    for name in duplicates:
        dups = idx==name
        ret = [ fmt%(name,i) if (i!=0 or not ignoreFirst) else name
                      for i in range(dups.sum()) ]
        idx.loc[dups] = ret
    return pd.Index(idx)

使用以下功能:

df.columns = dedupIndex(df.columns)
# Result: ['blah', 'blah2', 'blah3', 'blah.001', 'blah.002']
df.columns = dedupIndex(df.columns, fmt='%s #%d', ignoreFirst=False)
# Result: ['blah #0', 'blah2', 'blah3', 'blah #1', 'blah #2']

答案 7 :(得分:0)

感谢@Lamakaha提供解决方案。您的想法使我有机会对其进行修改并使其在所有情况下均可行。

我正在使用Python 3.7.3版本。

我在您的数据集上尝试了您的一段代码,该数据集只有一个重复的列,即两个具有相同名称的列。不幸的是,列名保持原样,没有重命名。最重要的是,我警告说"get_duplicates()已过时,并将在以后的版本中删除。”我使用duplicated()unique()代替get_duplicates(),无法产生预期的结果。

我已经稍微修改了您的代码段,现在对我的数据集以及其他一般情况下的代码都适用。

以下是在问题中提到的示例数据集上对代码进行修改和未修改的代码以及结果:


df=pd.DataFrame(np.arange(2*5).reshape(2,5))

df.columns=['blah','blah2','blah3','blah','blah']
df

cols=pd.Series(df.columns)

for dup in df.columns.get_duplicates(): 
    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

df
  

f:\ Anaconda3 \ lib \ site-packages \ ipykernel_launcher.py:2:FutureWarning:   “ get_duplicates”已弃用,以后将被删除   发布。您可以改用idx [idx.duplicated()]。unique()

输出:

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

三个“ blah”中的两个未正确重命名。


修改后的代码

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

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))]
df.columns=cols

df

输出:

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

这是在另一个示例上运行的修改后的代码:

cols = pd.Series(['X', 'Y', 'Z', 'A', 'B', 'C', 'A', 'A', 'L', 'M', 'A', 'Y', 'M'])

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))]

cols

Output:
0       X
1       Y
2       Z
3       A
4       B
5       C
6     A_1
7     A_2
8       L
9       M
10    A_3
11    Y_1
12    M_1
dtype: object

希望这对寻求上述问题答案的人有所帮助。

答案 8 :(得分:0)

使用一些测试创建了一个函数,因此应该将其放置好;这与Lamakaha's excellent solution有点不同,因为它重命名了重复列的首次出现:

this.get('username')

答案 9 :(得分:0)

我们可以为每个列分配一个不同的名称。

支持重复的列名就像= [a,b,c,d,d,c]

然后仅创建要分配的名称列表:

C = [a,b,c,d,D1,C1]
df.columns = c

这对我有用。

答案 10 :(得分:0)

我刚刚写了这段代码,它使用列表理解来更新所有重复的名称。

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)]