Pandas Merge - 如何避免重复列

use*_*092 55 python pandas

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

通过索引合并这些的最佳方法是什么,但不要取两份货币和约会日期.

每个数据框是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
...
Run Code Online (Sandbox Code Playgroud)

如果我做:

dfNew = merge(df, df2, left_index=True, right_index=True, how='outer')
Run Code Online (Sandbox Code Playgroud)

我明白了

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
Run Code Online (Sandbox Code Playgroud)

谢谢!...

EdC*_*ica 104

您可以计算仅在一个数据框中的列,并使用它来选择合并中的列的子集

cols_to_use = df2.columns - df.columns
Run Code Online (Sandbox Code Playgroud)

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

dfNew = merge(df, df2[cols_to_use], left_index=True, right_index=True, how='outer')
Run Code Online (Sandbox Code Playgroud)

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

对于0.15及更高版本,新的首选语法是:

cols_to_use = df2.columns.difference(df.columns)
Run Code Online (Sandbox Code Playgroud)

谢谢@odedbd

  • 如果键是一列并且名称相同怎么办?第一步就会将其丢弃。 (18认同)
  • 这很好,我只想更新0.15,这将给出一个弃用警告,建议新语法cols_to_use = df2.columns.difference(df.columns) (8认同)
  • 如果您使用left_on和right_on,则此解决方案不起作用. (2认同)

小智 55

我在以下suffixes选项中使用.merge():

dfNew = df.merge(df2, left_index=True, right_index=True,
                 how='outer', suffixes=('', '_y'))
Run Code Online (Sandbox Code Playgroud)

然后,您可以根据标志"_y"过滤列,即删除它们.

  • 如果它包含用于“过滤”的代码(这是相当简单的方法,但查找起来仍然很费时/容易记错),将是一个更有帮助的答案。即`dfNew.drop(list(dfNew.filter(regex ='_ y $')),axis = 1,inplace = True)` (8认同)

Ell*_*ins 14

基于@rprog 的回答,您可以使用负正则表达式将后缀和过滤步骤的各个部分组合成一行:

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

或使用df.join

dfNew = df.join(df2, lsuffix="DROP").filter(regex="^(?!.*DROP)")
Run Code Online (Sandbox Code Playgroud)

此处的正则表达式保留以“DROP”一词结尾的任何内容,因此请确保使用尚未出现在列中的后缀。


Jul*_*enD 5

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

销售.csv

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

收入.csv

    branch_id;城市;收入;state_id
    10;奥斯汀;100;德克萨斯州
    20;奥斯汀;83;德克萨斯州
    30;奥斯汀;4;德克萨斯州
    47;奥斯汀;200;德克萨斯州
    20;丹佛;83;一氧化碳
    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=';')
Run Code Online (Sandbox Code Playgroud)

执行合并命令时,我用_x空字符串替换后缀,然后我可以删除以_y

输出.csv

    id;城市;州;单位;branch_id;收入;state_id
    0;丹佛;一氧化碳;4;20;83;一氧化碳
    1;奥斯汀;TX;2;10;100;TX
    2;奥斯汀;德克萨斯州;2;20;83;德克萨斯州
    3;奥斯汀;德克萨斯州;2;30;4;德克萨斯州
    4;奥斯汀;德克萨斯州;2;47;200;德克萨斯州