Mar*_*bak 2 python merge dataframe pandas pandas-groupby
目前,我有两个数据框在“KEY”上进行合并。我的第一个数据框包含一个 KEY 和产品的原始价格。我的第二个数据框收集一个人每次付款的信息。我需要在 df1 中创建一个最终计算列,显示剩余余额。剩余余额是通过从 original_price 中减去 payment_price 来计算的。唯一需要注意的是,只有某些 price_codes 反映了付款(13、14 和 15)。
我不确定最好的方法是否使用合并,或者我是否可以简单地引用另一个 df 而不必合并(后一种方法似乎更理想,因为两个 dfs 都有 500,000,000+ 行),但我找不到太多内容这个特定的场景。
df1 = pd.DataFrame({'KEY': ['100000555', '100000009','100000034','100000035', '100000036'],
'original_price': [1205.20,1253.25,1852.15,1452.36,1653.21],
'area': [12, 13, 12,12,12]})
df2 = pd.DataFrame({'KEY': ['100000555', '100000009', '100000009', '100000009', '100000009','100000034','100000034', '100000034'],
'payment_price': [134.04, 453.43, 422.32,23.23,10.43,10.47,243.09,23.45],
'Price_code': ['13', '13', '14','15','16','13','14','15']})
Run Code Online (Sandbox Code Playgroud)
df1:
KEY area original_price
0 100000555 12 1205.20
1 100000009 13 1253.25
2 100000034 12 1852.15
3 100000035 12 1452.36
4 100000036 12 1653.21
Run Code Online (Sandbox Code Playgroud)
df2:
KEY payment_price Price_code
0 100000555 134.04 13
1 100000009 453.43 13
2 100000009 422.32 14
3 100000009 23.23 15
4 100000009 10.43 16
5 100000034 10.47 13
6 100000034 243.09 14
7 100000034 23.45 15
Run Code Online (Sandbox Code Playgroud)
我需要创建一个计算,如果它们与键匹配并且 price_code 值为 13,14 或 15,我需要从 df2 中减去任何 payment_price。
最后结果
KEY area original_price calculated_price
0 100000555 12 1205.20 1071.16 # (1205.20 - 134.04)
1 100000009 13 1253.25 354.27 # (1253.25 - 453.43 - 422.32 - 23.23)
2 100000034 12 1852.15 1575.14 # (1852.15 - 10.47 - 243.09 - 23.45)
3 100000035 12 1452.36 1452.36
4 100000036 12 1653.21 1653.21
Run Code Online (Sandbox Code Playgroud)
我最初的倾向是合并两个 dfs 并使用 groupby 语句执行计算。但我对此犹豫不决的是,这似乎资源很重,我的最终 df 将至少是行数的两倍。此外,我遇到了一个心理障碍,无法编写仅包含某些 price_codes 的计算。所以现在我想知道是否有更好的方法。我愿意接受其他方法或帮助处理此脚本。老实说,我不完全确定如何为类似这样的事情编写 price_codes 的条件。下面的代码首先合并dfs,然后创建一个列(remaining_price)。但是,对于 KEY 10000009,我只需要包括 price_codes 12、14、15 并排除 16,但当前包括 16。
result = pd.merge(df1, df2,how='left', on='KEY')
codes = [13,14,15]
result['remaining_price'] = result['original_price'] - result['payment_price'].groupby(result['KEY']).transform('sum')
Run Code Online (Sandbox Code Playgroud)
最后,我假设如果这是我使用的方法,我需要删除 KEY 和两个合并列(price_code、payment_price)上的所有重复行。
result = result.drop_duplicates(subset=['KEY'],keep='first')
Run Code Online (Sandbox Code Playgroud)
这是一种方法。不需要显式合并或删除重复项。这是您可能会看到性能改进的地方。
解决方案
s = df2[df2['Price_code'].isin([13, 14, 15])].groupby('KEY')['payment_price'].sum()
df1['calculated_price'] = df1['original_price'] - df1['KEY'].map(s).fillna(0)
Run Code Online (Sandbox Code Playgroud)
结果
KEY area original_price calculated_price
0 100000555 12 1205.20 1071.16
1 100000009 13 1253.25 354.27
2 100000034 12 1852.15 1575.14
3 100000035 12 1452.36 1452.36
4 100000036 12 1653.21 1653.21
Run Code Online (Sandbox Code Playgroud)
解释
df2根据需要按 Price_code过滤,按 KEY 汇总 payment_price,最后汇总。结果是将 KEY 映射到付款总和的系列。map将这些总和映射到 KEY indf1并从 original_price中减去。