熊猫-合并两个数据框,对相似的列求和,仅保留具有匹配键的行(内部联接)

时间:2020-02-24 22:28:56

标签: python pandas

我陷入了熊猫concatmerge函数之间的困境,努力做到两者兼得。我需要对名称和日期上的行进行内部联接,对通用列A和B求和,并保留类别中的值(确实,我可以在需要时将其添加到联接中,因为它们匹配)。

示例-

df1

| name | date     | A | B | category |
|------|----------|---|---|----------|
| W    | 1/1/2020 | 1 | 1 | home     |
| W    | 1/2/2020 | 1 | 1 | home     |
| Y    | 1/3/2020 | 1 | 1 | garden   |
| Y    | 1/4/2020 | 1 | 1 | garden   |

df2

| name | date     | A | B | category |
|------|----------|---|---|----------|
| W    | 1/1/2020 | 2 | 2 | home     |
| W    | 1/2/2020 | 1 | 1 | home     |
| Y    | 1/3/2020 | 1 | 1 | garden   |
| Y    | 1/5/2020 | 1 | 1 | garden   |

所需结果-

| name | date     | A | B | category |
|------|----------|---|---|----------|
| W    | 1/1/2020 | 3 | 3 | home     |
| W    | 1/2/2020 | 2 | 2 | home     |
| Y    | 1/3/2020 | 2 | 2 | garden   |

我发现merge将加入行,但是会复制未加入的任何列而不是对它们求和。

concat将对行求和,但不进行内部联接,因此我仅从一个数据帧或另一个数据帧中获取具有数据的行。我已经尝试过pd.concat([df_1, df_2], join='inner',但“内在”功能却无法满足我的要求。

3 个答案:

答案 0 :(得分:1)

我将在namedatecategory上使用groupby,并使用sum聚合(求和在A和{{1} })。不过,这会产生额外的列,因为日期为B1/4/2020的行不会消失,但总和为1。

这是代码:

1/5/2020

这给您:

import pandas as pd

df = pd.DataFrame({'name': ['W', 'W', 'Y', 'Y'], 
                   'date': ['1/1/2020', '1/2/2020', '1/3/2020', '1/4/2020 '],
                   'A': [1, 1, 1, 1],
                   'B': [1, 1, 1, 1],
                   'category': ['home', 'home', 'garden', 'garden']})

df2 = pd.DataFrame({'name': ['W', 'W', 'Y', 'Y'], 
                   'date': ['1/1/2020', '1/2/2020', '1/3/2020', '1/5/2020 '],
                   'A': [2, 1, 1, 1],
                   'B': [2, 1, 1, 1],
                   'category': ['home', 'home', 'garden', 'garden']})

df3 = pd.concat([df, df2]).groupby(by=['name', 'date', 'category']).sum()

如果您不想看到总和= 1的行,则可以过滤 A B name date category W 1/1/2020 home 3 3 1/2/2020 home 2 2 Y 1/3/2020 garden 2 2 1/4/2020 garden 1 1 1/5/2020 garden 1 1 或/和A的值

希望这会有所帮助。

答案 1 :(得分:0)

第一个“天真的”解决方案:

d3 = pd.merge(d1,d2, left_on = ["name","date","category"], right_on = ["name","date","category"])
d3 = d3.assign(A = d3.A_x + d3.A_y, B = d3.B_x + d3.B_y, ).drop(columns=["A_y","A_x","B_y","B_x"])

更好的解决方案,无需手动添加列:

key = ["name","date","category"]
d3 = pd.merge(d1,d2, left_on = key, right_on = key)[key]
d4 = pd.concat([d1, d2]).groupby(by=key).sum()
d5 = pd.merge(d3,d4,right_on = key, left_on = key)

结果:

     name        date    category  A  B
0   W       1/1/2020    home       3  3
1   W       1/2/2020    home       2  2
2   Y       1/3/2020    garden     2  2

使用pd.merge可以指定组合键["name","date","category"]连接2个数据帧。

答案 2 :(得分:0)

这个怎么样?

dff = df1
    .set_index(['name', 'date', 'category'])
    .add(df2.set_index(['name', 'date', 'category'])
    .reset_index()
    .dropna()
    .reindex(columns=df1.columns)

dff

输出:

    name    date    A   B   category
 0  W   1/1/2020    3   3   home
 1  W   1/2/2020    2   2   home
 2  Y   1/3/2020    2   2   garden

这就是你想要的吗?