给定2个数据帧
df1
Year Month Day Name value
2022 2 11 ADP1 5,3
2022 2 15 ADP2 300,2
2022 3 21 ADP1 7000,3
2022 3 25 ADP2 13,2
2022 8 15 ADP1 444,1
2022 8 5 ADP2 3333,2
df2
Name1 Name2 Date1 Date2
xx APD1 2022-02-23 2022-04-30
yy APD2 2022-05-23 2022-06-30
zz APD1 2022-07-01 2022-09-01
ww APD2 2022-07-15 2022-09-30
我想要以下输出
out
Name1 Name2 Date1 Date2 sum
xx APD1 2022-02-03 2022-04-30 7005,6
yy APD2 2022-05-23 2022-06-30 0
zz APD1 2022-07-01 2022-09-01 444,1
ww APD2 2022-07-15 2022-09-30 3333,2
换句话说:将df2中的Name2与df1中的Name进行比较,检查(Year,Month,Date(是否在Date1、Date2的范围内,然后对每个值求和
现在,我正在用for循环迭代一年、几个月,目前正在添加另一个for循环,持续几天。。。我敢肯定熊猫身上有一种巧妙的方式。我在摆弄lambda x:没有成功(还在学习(。有人能帮我找路吗?
df2 2022-02-23中有一个日期,在预期结果中是2022-02-03。我修复了它。此外,在df1中,value列有一个逗号形式的小数部分,我用点代替了它,就像大多数情况下一样,并将列类型转换为float。基于此,我假设您所有的数据都是字符串类型的,所以我把它们都做成这样。在df1的三个列中,有一个列的日期已经创建:
pd.to_datetime(df1[['Year', 'Month', 'Day']])
两个框架的日期列都从字符串转换为日期。
为了总结结果,使用了列表生成器(它比循环快得多(。在每次迭代中使用三个条件进行过滤。列表结果"aaa"存储在一个新列中。
import pandas as pd
df1 = pd.DataFrame(
{'Year': ['2022', '2022', '2022', '2022', '2022', '2022'], 'Month': ['2', '2', '3', '3', '8', '8'],
'Day': ['11', '15', '21', '25', '15', '5'],
'Name': ['ADP1', 'ADP2', 'ADP1', 'ADP2', 'ADP1', 'ADP2'],
'value': ['5,3', '300,2', '7000,3', '13,2', '444,1', '3333,2']})
df2 = pd.DataFrame(
{'Name1': ['xx', 'yy', 'zz', 'ww'], 'Name2': ['ADP1', 'ADP2', 'ADP1', 'ADP2'],
'Date1': ['2022-02-03', '2022-05-23', '2022-07-01', '2022-07-15'],
'Date2': ['2022-04-30', '2022-06-30', '2022-09-01', '2022-09-30']})
df1['Date'] = pd.to_datetime(df1[['Year', 'Month', 'Day']])
df2[['Date1', 'Date2']] = df2[['Date1', 'Date2']].apply(pd.to_datetime)
df1['value'] = df1['value'].str.replace(',', '.').astype(float)
aaa = [df1.loc[(df1['Date'] >= df2.loc[i, 'Date1']) & (df1['Date'] <= df2.loc[i, 'Date2']) &
(df1['Name'] == df2.loc[i, 'Name2']), 'value'].sum() for i in range(len(df2))]
df2['sum'] = aaa
输出
Name1 Name2 Date1 Date2 sum
0 xx ADP1 2022-02-03 2022-04-30 7005.6
1 yy ADP2 2022-05-23 2022-06-30 0.0
2 zz ADP1 2022-07-01 2022-09-01 444.1
3 ww ADP2 2022-07-15 2022-09-30 3333.2
关于"aaa"列表的更多详细信息:
1.(df1['Date']>=df2.loc[i,'Date1'](在每次迭代时,从df2.[Date1']中选择一行(而不是一列,即一个值(,并与列df1['Date']进行比较。
2.(df1['Date']<=df2.loc[i,'Date2'](与第一个条件相同。
3.(df1['Name']=df2.loc[i,'Name2'](类似地,只有在这里才检查字符串值是否匹配。
所有条件都与&,这与python和中的意思相同。获取一个布尔掩码,其中True是匹配的值。我们将其用作索引,以访问所需的值。这是左边的内容,在右边我们指定所需的列"value"。更好理解的伪代码:
df1.loc[index, 'value'].sum()
每次迭代的列表生成器将每次迭代的结果写入列表。loc表示使用显式索引,如前所述,索引(行(显示在左侧,列名显示在右侧。您可以通过将多个索引括在方括号中来指定它们。例如:
df1.loc[[0, 2, 3], 'value']]