pandas:合并两个不同名称的列?

Posted

技术标签:

【中文标题】pandas:合并两个不同名称的列?【英文标题】:pandas: Merge two columns with different names? 【发布时间】:2017-08-29 12:26:11 【问题描述】:

我正在尝试连接上方和下方的两个数据框。不能并排连接。

数据框包含相同的数据,但是,在第一个数据框中,一列的名称可能为“ObjectType”,而在第二个数据框中,该列的名称可能为“ObjectClass”。当我这样做时

df_total = pandas.concat ([df0, df1])

df_total 将有两个列名,一个带有“ObjectType”,另一个带有“ObjectClass”。在这两列中的每一列中,一半的值将是“NaN”。所以我必须手动将这两列合并为一个,这很痛苦。

我可以以某种方式将两列合并为一列吗?我想有一个功能可以做这样的事情:

df_total = pandas.merge_many_columns(input=["ObjectType,"ObjectClass"], output=["MyObjectClasses"]

合并两列并创建一个新列。我已经研究过 melt() 但它并没有真正做到这一点?

(如果我能指定发生碰撞时会发生什么,假设两列包含值,在这种情况下,我提供一个 lambda 函数,上面写着“保持最大值”,“使用平均值"等)

【问题讨论】:

如果您来这里是为了了解如何实际合并具有不同列名的两个 DataFrame,您可以了解更多信息here。 【参考方案1】:

您可以使用 combine_first 将由 Nan 分隔的两列合并为一列

>>> import numpy as np
>>> import pandas as pd
>>>
>>> df0 = pd.DataFrame('ObjectType':[1,2,3],
                    'B':[4,5,6],
                    'C':[7,8,9])

>>> df1 = pd.DataFrame('ObjectClass':[1,2,3],
                    'B':[4,5,6],
                    'C':[7,8,9])

>>> df = pd.concat([df0, df1])
>>> df['ObjectType'] = df['ObjectType'].combine_first(df['ObjectClass'])
>>> df['ObjectType']

0    1
1    2
2    3
0    1
1    2
3    3
Name: ObjectType, dtype: float64

【讨论】:

据我了解,他在连接后得到了满是 Nan 的 df,现在正在寻找一种合并两列的方法。 这正是我所追求的。谢谢!也许您可以改为编辑最后一行?我花了 15 分钟才弄清楚这一点,所以如果可以添加,我将不胜感激: df["ObjectType"] = df['ObjectType'].combine_first(df['ObjectClass']) 对不起,但我认为“update()”比“combine_first()”更Pythonic。我想选择两者作为解决方案。【参考方案2】:

我认为您可以先重命名列以对齐两个 DataFrame 中的数据:

df0 = pd.DataFrame('ObjectType':[1,2,3],
                   'B':[4,5,6],
                   'C':[7,8,9])

#print (df0)

df1 = pd.DataFrame('ObjectClass':[1,2,3],
                   'B':[4,5,6],
                   'C':[7,8,9])

#print (df1)

inputs= ["ObjectType","ObjectClass"]
output= "MyObjectClasses"

#dict comprehension 
d = x:output for x in inputs
print (d)
'ObjectType': 'MyObjectClasses', 'ObjectClass': 'MyObjectClasses'

df0 = df0.rename(columns=d)
df1 = df1.rename(columns=d)
df_total = pd.concat([df0, df1], ignore_index=True)
print (df_total)
   B  C  MyObjectClasses
0  4  7                1
1  5  8                2
2  6  9                3
3  4  7                1
4  5  8                2
5  6  9                3

编辑:

更简单的是update(工作inplace):

df = pd.concat([df0, df1])
df['ObjectType'].update(df['ObjectClass'])
print (df)
   B  C  ObjectClass  ObjectType
0  4  7          NaN         1.0
1  5  8          NaN         2.0
2  6  9          NaN         3.0
0  4  7          1.0         1.0
1  5  8          2.0         2.0
2  6  9          3.0         3.0

fillna,但随后需要删除原始列列:

df = pd.concat([df0, df1])
df["ObjectType"] = df['ObjectType'].fillna(df['ObjectClass'])
df = df.drop('ObjectClass', axis=1)
print (df)
   B  C  ObjectType
0  4  7         1.0
1  5  8         2.0
2  6  9         3.0
0  4  7         1.0
1  5  8         2.0
2  6  9         3.0

df = pd.concat([df0, df1])
df["MyObjectClasses"] = df['ObjectType'].fillna(df['ObjectClass'])
df = df.drop(['ObjectType','ObjectClass'], axis=1)
print (df)
   B  C  MyObjectClasses
0  4  7              1.0
1  5  8              2.0
2  6  9              3.0
0  4  7              1.0
1  5  8              2.0
2  6  9              3.0

编辑1:

时间安排

df0 = pd.DataFrame('ObjectType':[1,2,3],
                   'B':[4,5,6],
                   'C':[7,8,9])

#print (df0)

df1 = pd.DataFrame('ObjectClass':[1,2,3],
                   'B':[4,5,6],
                   'C':[7,8,9])

#print (df1)
df0 = pd.concat([df0]*1000).reset_index(drop=True)
df1 = pd.concat([df1]*1000).reset_index(drop=True)

inputs= ["ObjectType","ObjectClass"]
output= "MyObjectClasses"

#dict comprehension 
d = x:output for x in inputs

In [241]: %timeit df_total = pd.concat([df0.rename(columns=d), df1.rename(columns=d)], ignore_index=True)
1000 loops, best of 3: 821 µs per loop

In [240]: %%timeit
     ...: df = pd.concat([df0, df1])
     ...: df['ObjectType'].update(df['ObjectClass'])
     ...: df = df.drop(['ObjectType','ObjectClass'], axis=1)
     ...: 

100 loops, best of 3: 2.18 ms per loop

In [242]: %%timeit
     ...: df = pd.concat([df0, df1])
     ...: df['MyObjectClasses'] = df['ObjectType'].combine_first(df['ObjectClass'])
     ...: df = df.drop(['ObjectType','ObjectClass'], axis=1)
     ...: 
100 loops, best of 3: 2.21 ms per loop

In [243]: %%timeit 
     ...: df = pd.concat([df0, df1])
     ...: df['MyObjectClasses'] = df['ObjectType'].fillna(df['ObjectClass'])
     ...: df = df.drop(['ObjectType','ObjectClass'], axis=1)
     ...: 
100 loops, best of 3: 2.28 ms per loop

【讨论】:

是的,这可能有效。但是,我有很多列,我只想重命名两列。您的解决方案是否仅在数据框有两列时才有效? 我认为这是通用解决方案 - 只需在两个数据框中使用相同的列名。 感谢您的帮助,但我选择了“combine_first”的答案,因为它更简单。 :) 我添加了 2 个解决方案,但我认为 rename 更好,如果使用更多不同的列并且需要将 input=["ObjectType,"ObjectClass"] 映射到 output=["MyObjectClasses"] 嗯,主要看你需要什么。 combine_firstfillnaupdate 也更慢(参见编辑后的答案),int 被转换为 float,所以 astype(int) last 是必要的。 ;) 美好的一天!

以上是关于pandas:合并两个不同名称的列?的主要内容,如果未能解决你的问题,请参考以下文章

Pandas:合并具有相似名称的列

合并 pandas 中列名不同且长度不同的两个数据框

熊猫合并具有不同名称的列并避免重复[重复]

在 Pandas 中合并数据框(没有列名)

使用具有相同字符串但顺序不同的列合并两个 data.frame

Pandas 通过取列之间的平均值来合并两个数据框