使用新列名迭代合并 pandas 列

Posted

技术标签:

【中文标题】使用新列名迭代合并 pandas 列【英文标题】:Iteratively merge panda columns with new column names 【发布时间】:2021-11-25 09:54:06 【问题描述】:

假设我在一个循环中迭代地合并一个 panda 数据框,但是在两次或三次迭代之后,panda 重复列名例如考虑下面的例子,我迭代地合并列,但为了简单起见没有循环:

A= 'Name':['A','B','C'],'GPA':[4.0,3.80,3.70], 'School':['U','U','U'], 'Time':[22,26,30]
A1 = pd.DataFrame(A)
B= 'Name':['D','E','F'],'GPA':[3.50,3.70,3.60], 'School':['S','S','S'],'Time':[34,44,54]
B1 = pd.DataFrame(B)
C= 'Name':['G','H','I'],'GPA':[3.70,3.50,3.70], 'School':['C','C','C'],'Time':[76,86,96]
C1 = pd.DataFrame(C)
L= [A1,B1,C1]
comb = A1
for ii in L[1:]:
    comb = pd.concat([comb,ii],ignore_index=True)
comb

B = pd.merge(comb, comb, on=['Name','GPA'])
C = pd.merge(B, comb, on=['Name','GPA'])
D = pd.merge(C, comb, on=['Name','GPA'])

您看到 Panda 重复了两次 School_x 和 School_y 名称,是否可以将其更改为 School_x 和 School_y、School_z 和 School_t。我不是在谈论之后重命名它,而是强制合并为不同的列选择新的列名。否则如何区分具有 1000 列的数据框并想象 500 列具有相同的列名。

更新:以上只是一个示例,假设您正在循环中合并多个数据帧,如下所示:

  for ii in list:
      df  = df.merge(A,on = 'some column', how = 'outer')

那么你如何迭代地更改列名,在我看来每次相同的列都会重复,即使有后缀。

【问题讨论】:

有后缀见文档后缀列表,默认为 (“_x”, “_y”) 长度为 2 的序列,其中每个元素可选地是一个字符串,指示要添加到重叠列名称的后缀分别在左侧和右侧。传递 None 值而不是字符串,以指示从左侧或右侧开始的列名应保持原样,不带后缀。至少其中一个值不得为无。 pandas.pydata.org/docs/reference/api/… 【参考方案1】:

尝试将 suffixes 参数更改为 ('_z', '_t') 的元组:

B = pd.merge(comb, comb, on=['Name','GPA'])
C = pd.merge(B, comb, on=['Name','GPA'])
D = pd.merge(C, comb, on=['Name','GPA'], suffixes=('_z', '_t'))

>>> D
  Name  GPA School_x  Time_x School_y  Time_y School_z  Time_z School_t  Time_t
0    A  4.0        U      22        U      22        U      22        U      22
1    B  3.8        U      26        U      26        U      26        U      26
2    C  3.7        U      30        U      30        U      30        U      30
3    D  3.5        S      34        S      34        S      34        S      34
4    E  3.7        S      44        S      44        S      44        S      44
5    F  3.6        S      54        S      54        S      54        S      54
6    G  3.7        C      76        C      76        C      76        C      76
7    H  3.5        C      86        C      86        C      86        C      86
8    I  3.7        C      96        C      96        C      96        C      96
>>> 

pd.merge 文档中所述:

参数: ... ...

后缀:类似列表,默认为 (“_x”, “_y”)

长度为 2 的序列,其中每个元素可选地是一个字符串,指示要分别添加到左右重叠列名的后缀。传递 None 值而不是字符串,以指示从左侧或右侧开始的列名应保持原样,不带后缀。至少有一个值不能为 None。

... ...


编辑:

对于该问题的最新更新,请尝试创建一个迭代器并使用next

functools.reduce 会更好:

from functools import reduce
from string import ascii_lowercase
it = iter(ascii_lowercase)
print(reduce(lambda x, y: pd.merge(x, y, on=['Name','GPA'], suffixes=('_' + next(it), '_' + next(it))), [comb for _ in range(4)]))

输出:

  Name  GPA School_a  Time_a School_b  Time_b School_e  Time_e School_f  Time_f
0    A  4.0        U      22        U      22        U      22        U      22
1    B  3.8        U      26        U      26        U      26        U      26
2    C  3.7        U      30        U      30        U      30        U      30
3    D  3.5        S      34        S      34        S      34        S      34
4    E  3.7        S      44        S      44        S      44        S      44
5    F  3.6        S      54        S      54        S      54        S      54
6    G  3.7        C      76        C      76        C      76        C      76
7    H  3.5        C      86        C      86        C      86        C      86
8    I  3.7        C      96        C      96        C      96        C      96

如您所见,我使用 [comb for _ in range(4)] 创建了一个列表推导式,它将循环和合并 4 次,要更改次数只需更改数字即可,即 [comb for _ in range(10)]

对于函数:

from functools import reduce
from string import ascii_lowercase
def cumulative_merge(df, n):
    it = iter(ascii_lowercase)
    return reduce(lambda x, y: pd.merge(x, y, on=['Name','GPA'], suffixes=('_' + next(it), '_' + next(it))), [comb for _ in range(n)])

执行:

print(cumulative_merge(df, 4))

输出:

  Name  GPA School_a  Time_a School_b  Time_b School_e  Time_e School_f  Time_f
0    A  4.0        U      22        U      22        U      22        U      22
1    B  3.8        U      26        U      26        U      26        U      26
2    C  3.7        U      30        U      30        U      30        U      30
3    D  3.5        S      34        S      34        S      34        S      34
4    E  3.7        S      44        S      44        S      44        S      44
5    F  3.6        S      54        S      54        S      54        S      54
6    G  3.7        C      76        C      76        C      76        C      76
7    H  3.5        C      86        C      86        C      86        C      86
8    I  3.7        C      96        C      96        C      96        C      96

【讨论】:

谢谢,但假设我有 10 列是否有任何自动方法来更改后缀名称,例如,如果您在循环中像这样 df = df.merge(A, on = ' ') 那么后缀会再次重复 @user59419 检查我的 Edit: 部分,它甚至不需要循环,我还为它创建了一个函数,现在它适用于任何数量的累积合并。

以上是关于使用新列名迭代合并 pandas 列的主要内容,如果未能解决你的问题,请参考以下文章

迭代地添加计算列,然后将新数据添加到 Pandas 数据框(python 3.7.1)

使用 Pandas 迭代地将列添加到数据框中

python--pandas合并与连接

pandas数据合并之append与concat

Pandas:合并具有相同列名的 pandas 列

给 pandas 一个可迭代的 python 和一个 pd.Series 的列之间的区别