熊猫合并-如何避免重复的列


96

我正在尝试在两个数据帧之间合并。每个数据帧都有两个索引级别(日期,客户)。在列中,例如,某些列在两者之间匹配(货币,日期)。

按索引合并这些内容的最佳方法是什么,但不要采用两个副本的货币和日期。

每个数据框都是90列,所以我试图避免用手将所有内容写出来。

df:                 currency  adj_date   data_col1 ...
date        cusip
2012-01-01  XSDP      USD      2012-01-03   0.45
...

df2:                currency  adj_date   data_col2 ...
date        cusip
2012-01-01  XSDP      USD      2012-01-03   0.45
...

如果我做:

dfNew = merge(df, df2, left_index=True, right_index=True, how='outer')

我懂了

dfNew:              currency_x  adj_date_x   data_col2 ... currency_y adj_date_y
date        cusip
2012-01-01  XSDP      USD      2012-01-03   0.45             USD         2012-01-03

谢谢!...

Answers:


149

您可以算出仅在一个DataFrame中的列,并使用它来选择合并中列的子集。

cols_to_use = df2.columns.difference(df.columns)

然后执行合并(请注意,这是一个索引对象,但是它有一个方便的tolist()方法)。

dfNew = merge(df, df2[cols_to_use], left_index=True, right_index=True, how='outer')

这将避免合并中的任何列冲突。


4
如果键是一列,并且名称相同,该怎么办?第一步将删除它。
格拉

94

我在中使用该suffixes选项.merge()

dfNew = df.merge(df2, left_index=True, right_index=True,
                 how='outer', suffixes=('', '_y'))
dfNew.drop(dfNew.filter(regex='_y$').columns.tolist(),axis=1, inplace=True)

谢谢@ijoseph


18
如果它包含用于filtering的代码(这非常简单,但查找起来仍然很耗时/容易记错),将是一个更有帮助的答案。即 dfNew.drop(list(dfNew.filter(regex='_y$')), axis=1, inplace=True)
ijoseph '19

6

以@rprog的答案为基础,可以使用负正则表达式将后缀和filter步骤的各个部分组合为一行:

dfNew = df.merge(df2, left_index=True, right_index=True,
             how='outer', suffixes=('', '_DROP')).filter(regex='^(?!.*_DROP)')

或使用df.join

dfNew = df.join(df2, lsuffix="DROP").filter(regex="^(?!.*DROP)")

这里的正则表达式保留了所有以单词“ DROP”结尾的内容,因此请确保使用未在各列之间出现的后缀。


5

我刚接触Pandas,但是我想实现相同的目的,自动避免使用_x或_y的列名并删除重复的数据。我终于用这个做了回答,这一个从#1

sales.csv

    城市;州;单位
    门多西诺; CA; 1
    丹佛; CO; 4
    奥斯汀;德克萨斯州; 2

Revenue.csv

    branch_id; city; revenue; state_id
    10;奥斯丁; 100; TX
    20;奥斯丁; 83; TX
    30;奥斯丁; 4; TX
    47;奥斯丁; 200; TX
    20;丹佛; 83; CO
    30;斯普林菲尔德; 4;我

merge.py导入熊猫

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)


sales = pandas.read_csv('data/sales.csv', delimiter=';')
revenue = pandas.read_csv('data/revenue.csv', delimiter=';')

result = pandas.merge(sales, revenue,  how='inner', left_on=['state'], right_on=['state_id'], suffixes=('', '_y'))
drop_y(result)
result.to_csv('results/output.csv', index=True, index_label='id', sep=';')

当执行merge命令时,我将_x后缀替换为空字符串,并且可以删除以结尾的列_y

output.csv

    id; city; state; units; branch_id; revenue; state_id
    0;丹佛; CO; 4; 20; 83; CO
    1; Austin; TX; 2; 10; 100; TX
    2; Austin; TX; 2; 20; 83; TX
    3; Austin; TX; 2; 30; 4; TX
    4; Austin; TX; 2; 47; 200; TX

0

可以解决这个问题,但是我编写了一个基本上处理多余列的函数:

def merge_fix_cols(df_company,df_product,uniqueID):
    
    df_merged = pd.merge(df_company,
                         df_product,
                         how='left',left_on=uniqueID,right_on=uniqueID)    
    for col in df_merged:
        if col.endswith('_x'):
            df_merged.rename(columns = lambda col:col.rstrip('_x'),inplace=True)
        elif col.endswith('_y'):
            to_drop = [col for col in df_merged if col.endswith('_y')]
            df_merged.drop(to_drop,axis=1,inplace=True)
        else:
            pass
    return df_merged

似乎可以很好地与我的合并!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.