Pandas: Merge on 2 columns



我正在处理一个大型数据集,并遇到以下问题:假设我正在测量一种物质("子输入"(到介质("id"(中的输入。对于每个子输入,我计算了它将到达介质另一侧的年份("y-rrival"(。有时几个子输入在同一年到达,有时一年内没有实质内容到达。

示例:

import pandas as pd
import numpy as np
ids = [1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3]
year= [2000,2001,2002,2003,2004,2005,1990,1991,1992,1993,1994,1995,2000,2001,2002,2003,2004,2005]
in1 = [20,40,10,30,50,80,
60,10,10,40,np.NaN,np.NaN,
np.NaN,120,30,70,60,90]
arr = [2002,2004,2004,2004,2005,np.NaN,
1991,1992,np.NaN,1995,1995,np.NaN,
2001,2002,2004,2004,2005,np.NaN]
dictex3 ={"id":ids,"year":year,"sub-input":in1, "y-arrival":arr}
dfex3 = pd.DataFrame(dictex3)

然后我计算了";子输入";对于每个";y-arrival";使用以下代码:

dfex3["input_sum_tf"] = dfex3.groupby(["id","y-arrival"])["sub-input"].transform(sum)
print(dfex3)
id  year  sub-input  y-arrival  input_sum_tf
0    1  2000       20.0     2002.0          20.0
1    1  2001       40.0     2004.0          80.0
2    1  2002       10.0     2004.0          80.0
3    1  2003       30.0     2004.0          80.0
4    1  2004       50.0     2005.0          50.0
5    1  2005       80.0        NaN           NaN
6    2  1990       60.0     1991.0          60.0
7    2  1991       10.0     1992.0          10.0
8    2  1992       10.0        NaN           NaN
9    2  1993       40.0     1995.0          40.0
10   2  1994        NaN     1995.0          40.0
11   2  1995        NaN        NaN           NaN
12   3  2000        NaN     2001.0           0.0
13   3  2001      120.0     2002.0         120.0
14   3  2002       30.0     2004.0         100.0
15   3  2003       70.0     2004.0         100.0
16   3  2004       60.0     2005.0          60.0
17   3  2005       90.0        NaN           NaN

现在,对于每个";id";到达目的地的输入的总和为"0";y-arrival";已计算。

目标是对这些值进行重新排序,以便为每个id和每年显示该年将到达的子输入的总和。示例:

  • id=1,年份=2000->无y到达时间=2000-->=NaN
  • id=1,年份=2001->无y到达时间=2001-->=NaN
  • id=1,年份=2002-->y-rrival=2002具有input_sum_tf=20->=20
  • id=1,年份=2003->无y到达时间=2003-->=NaN
  • id=1,年份=2004->y-rrival=2004具有input_sum_tf=80->=80

;input_ sum_tf";是某一年内到达的物质的总和。值";80〃;2004年是2001年、2002年和2003年的子投入的总和,因为所有这些都是在2004年到达的(y-rrival=2004(。

结果("input_sum"(应该是这样的:

0       NaN
1       NaN
2      20.0
3       NaN
4      80.0
5      50.0
6       NaN
7      60.0
8      10.0
9       NaN
10      NaN
11     40.0
12      NaN
13      NaN
14    120.0
15      NaN
16    100.0
17     60.0

我的方法:

  • 我试图通过在两列上使用panda的merge函数来解决这个问题,但结果不太正确。到目前为止,我的代码只适用于前5列
dfex3['input_sum'] = dfex3.merge(dfex3, left_on=['id','y-arrival'],
right_on=['id','year'], 
how='right')['input_sum_tf_x']
dfex3["input_sum"]
0       NaN
1       NaN
2      20.0
3       NaN
4      80.0
5      80.0
6      80.0
7      50.0
8       NaN
9      60.0
10     10.0
11      NaN
12      NaN
13     40.0
14     40.0
15      NaN
16      0.0
17    120.0

任何帮助都将不胜感激!

问题是您的代码试图在'year'和'y-rrival'上合并,所以当您只想要一个匹配时,它会进行多个匹配。例如,年份=2004的第4行将匹配y-rrival=2004的3次(第1-3行(,因此输出行4-6中的80的重复。

使用groupby获取每个id/y-arrival组合的最后一行(看起来你不想要'input_sum_tf'为零的匹配(:

df_last = dfex3.groupby(['id', 'y-arrival']).last().reset_index()
df_last = df_last[df_last['input_sum_tf'] != 0]

然后合并:

dfex3.merge(df_last, 
left_on=['id', 'year'], 
right_on=['id', 'y-arrival'],
how='left')['input_sum_tf_y']
0       NaN
1       NaN
2      20.0
3       NaN
4      80.0
5      50.0
6       NaN
7      60.0
8      10.0
9       NaN
10      NaN
11     40.0
12      NaN
13      NaN
14    120.0
15      NaN
16    100.0
17     60.0

最新更新