合并两个Pandas数据框会导致“重复”列。

11

我想要合并两个包含相同键列的数据框。一些其他列也具有相同的标题,尽管行数不相等,在合并这些列后,它们将“重复”,原始标题带有后缀_x、_y等。

有人知道如何让pandas在下面的示例中删除重复的列吗?

这是我的Python代码:

import pandas as pd

holding_df = pd.read_csv('holding.csv')
invest_df = pd.read_csv('invest.csv')

merge_df = pd.merge(holding_df, invest_df, on='key', how='left').fillna(0)
merge_df.to_csv('merged.csv', index=False)

CSV文件中包含以下内容:

左侧数据框的第一行(holding_df):

key, dept_name, res_name, year, need, holding
DeptA_ResA_2015, DeptA, ResA, 2015, 1, 1
DeptA_ResA_2016, DeptA, ResA, 2016, 1, 1
DeptA_ResA_2017, DeptA, ResA, 2017, 1, 1
...

正确的数据框(invest_df)

key, dept_name, res_name, year, no_of_inv, inv_cost_wo_ice
DeptA_ResA_2015, DeptA, ResA, 2015, 1, 1000000
DeptA_ResB_2015, DeptA, ResB, 2015, 2, 6000000
DeptB_ResB_2015, DeptB, ResB, 2015, 1, 6000000
...

合并后的结果

key, dept_name_x, res_name_x, year_x, need, holding, dept_name_y, res_name_y, year_y, no_of_inv, inv_cost_wo_ice
DeptA_ResA_2015, DeptA, ResA, 2015, 1, 1, DeptA, ResA, 2015.0, 1.0, 1000000.0
DeptA_ResA_2016, DeptA, ResA, 2016, 1, 1, 0, 0, 0.0, 0.0, 0.0
DeptA_ResA_2017, DeptA, ResA, 2017, 1, 1, 0, 0, 0.0, 0.0, 0.0
DeptA_ResA_2018, DeptA, ResA, 2018, 1, 1, 0, 0, 0.0, 0.0, 0.0
DeptA_ResA_2019, DeptA, ResA, 2019, 1, 1, 0, 0, 0.0, 0.0, 0.0
...

增加更多的合并列是否仍然能够给您所需的结果?merge_df = pd.merge(holding_df, invest_df, on=['key', 'dept_name', 'res_name', 'year'], how='left').fillna(0) - EdChum
_x_y 列来自于合并中的左右两个数据框。您需要指定更多的列来表明它们是相同的(pandas 不知道这一点)。 - Simeon Visser
你可以将列的列表传递给 drop,但是重命名需要通过将字典传递给 rename来实现。 - EdChum
这意味着左侧或右侧的值不一致或缺失,因此您需要重命名 _x 列并删除所有 _y 列,您需要使用 droprename,建议使用动态方法来完成此操作。 - EdChum
3个回答

9
你有额外的带有后缀'_x'和'_y'的列是因为你要合并的列没有匹配的值,所以这种冲突会产生额外的列。在这种情况下,你需要删除额外的'_y'列并重命名'_x'列:
In [145]:
# define our drop function
def drop_y(df):
    # list comprehension of the cols that end with '_y'
    to_drop = [x for x in df if x.endswith('_y')]
    df.drop(to_drop, axis=1, inplace=True)

drop_y(merged)
merged
Out[145]:
               key  dept_name_x  res_name_x   year_x   need   holding  \
0  DeptA_ResA_2015        DeptA        ResA     2015      1         1   
1  DeptA_ResA_2016        DeptA        ResA     2016      1         1   
2  DeptA_ResA_2017        DeptA        ResA     2017      1         1   

    no_of_inv   inv_cost_wo_ice  
0           1           1000000  
1           0                 0  
2           0                 0  
In [146]:
# func to rename '_x' cols
def rename_x(df):
    for col in df:
        if col.endswith('_x'):
            df.rename(columns={col:col.rstrip('_x')}, inplace=True)
rename_x(merged)
merged
Out[146]:
               key  dept_name  res_name   year   need   holding   no_of_inv  \
0  DeptA_ResA_2015      DeptA      ResA   2015      1         1           1   
1  DeptA_ResA_2016      DeptA      ResA   2016      1         1           0   
2  DeptA_ResA_2017      DeptA      ResA   2017      1         1           0   

    inv_cost_wo_ice  
0           1000000  
1                 0  
2                 0 

编辑 如果您将常用列添加到合并中,则不应生成重复的列,除非这些列上的匹配项不匹配:

merge_df = pd.merge(holding_df, invest_df, on=['key', 'dept_name', 'res_name', 'year'], how='left').fillna(0)

但是它们确实有匹配的值!它们在重复的列中具有匹配的键和匹配的值,然后还有两个只在右侧数据帧中而不在左侧数据帧中的附加列(因此进行合并)。 - larslovlie
1
不,这不应该发生,重复的列只会出现在键不同的情况下,因此您的数据存在问题。 - EdChum
我一定搞砸了,因为将多个列添加到on参数中(正如您在评论中首先建议的那样)确实会产生所需的结果。非常抱歉,不知道我自己测试时做错了什么。如果您将您的评论写成一个简短的答案,我会将其标记为正确的。 - larslovlie
我刚刚做了这个,结果我得到了重复的_x和_y列,并且没有任何匹配的值。我把它放到Excel中并创建了新列来检查this_x中的值是否等于this_y中的值,但每一行都返回TRUE。所以这肯定是不正确的。 - Korzak

6

在左连接后,即使列的数据相同,我也遇到了重复列的问题。我进行了查询,并发现NaN值即使两个列都是NaN,在pandas 0.14中也被认为是不同的。但是一旦升级到0.15,这个问题就消失了,这就解释了为什么它后来能够正常工作,你可能已经升级了。


1

虽然不是完全的答案,但是pd.merge提供了一个参数来帮助您决定哪些重叠的列应该添加后缀

merge_df = pd.merge(holding_df, invest_df, on='key', how='left', suffixes=('_holding', '_invest')).fillna(0)

如果您决定保留这两个列(或者想要检查为什么保留了这些列),更有意义的名称可能会有所帮助。
请参阅文档以获取更多参考资料。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接