Python 熊猫总和值基于 Date&String



给定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']]

最新更新