我有两个表:一个(‘Sales’)包含销售数据(商品类型、销售日期和数量),另一个(‘Ref’)包含商品类型和参考日期.

我想在第二个表中添加一个列,该列将显示自参考日期起七天内相应商品的销售总量.

以下是示例数据:

sales = pd.DataFrame({'Fruit': {0: 'apples',  1: 'oranges',  2: 'pears',  3: 'apples',  4: 'apples',  5: 'bananas',  6: 'oranges', 7: 'pears',  8: 'pears',  9: 'oranges',  10: 'bananas',  11: 'apples',  12: 'pears',  13: 'pears', 14: 'apples',  15: 'pears',  16: 'oranges',  17: 'oranges',  18: 'pears'},
                      'Date': {0: '2023-07-07',  1: '2023-02-05',  2: '2023-08-16',  3: '2023-07-26',  4: '2023-07-14', 5: '2024-02-01',  6: '2023-09-19',  7: '2023-04-08',  8: '2023-06-08',  9: '2023-05-15', 10: '2023-10-20',  11: '2023-07-25',  12: '2023-07-31',  13: '2023-10-08',  14: '2023-06-28', 15: '2023-08-15',  16: '2023-05-14',  17: '2023-07-28',  18: '2023-07-29'},
                      'Quantity': {0: 18,  1: 10,  2: 10,  3: 20,  4: 16,  5: 14,  6: 18,  7: 18,  8: 14,  9: 19,  10: 16, 11: 16,  12: 17,  13: 10,  14: 16,  15: 15,  16: 18,  17: 20,  18: 19}})
sales['Date'] = pd.to_datetime(sales['Date'])

ref = pd.DataFrame({'Fruit': {0: 'apples', 1: 'bananas',  2: 'oranges',  3: 'apples',  4: 'pears', 5: 'oranges',  6: 'bananas',  7: 'oranges',  8: 'oranges'}, 
                    'Date': {0: '2023-07-25',  1: '2023-12-27',  2: '2023-07-13',  3: '2023-06-27',  4: '2023-07-08',  5: '2023-09-17', 6: '2023-10-25',  7: '2023-10-05',  8: '2023-04-14'}})
ref['Date'] = pd.to_datetime(ref['Date'])

例如,REF的第一行应该显示36个(2023-07-36年的20个苹果和2023-07-25年的16个苹果).

如果我使用的是Excel,我会使用以下公式:=SUMIF(sales.Quantity,sales.Fruit,ref.Fruit,sale.Date,">="&ref.Date-7,sales.Date,"<="&ref.Date+7).

在Python中,我可以获得所需的单项结果,如下所示:

sales[(sales['Fruit']=='apples')&
      (sales['Date']>=pd.to_datetime('2023-07-25')-pd.to_timedelta(7, unit='d'))&
      (sales['Date']<=pd.to_datetime('2023-07-25')+pd.to_timedelta(7, unit='d'))]['Quantity'].sum()

并使用iloc:

sales[(sales['Fruit']==ref.iloc[0,0])&
      (sales['Date']>=ref.iloc[0,1]-pd.to_timedelta(7, unit='d'))&
      (sales['Date']<=ref.iloc[0,1]+pd.to_timedelta(7, unit='d'))]['Quantity'].sum()

但是,当我try 添加一个新的列来引用这个计算时,我得到了‘ValueError:Can Can Compare Under-Label Series Object’.

ref['Total'] = sales[(sales['Fruit']==ref.iloc[ref.index,0])&
      (sales['Date']>=ref.iloc[ref.index,1]-pd.to_timedelta(7, unit='d'))&
      (sales['Date']<=ref.iloc[ref.index,1]+pd.to_timedelta(7, unit='d'))]['Quantity'].sum()

我猜我用ref.index代替iloc中的0来得到我需要的数字是错误的-我应该用什么来代替?

推荐答案

您可以使用pyjanitor中的conditional_join:

ref['start'] = ref['Date'] - pd.to_timedelta(7, unit='d')
ref['end'] = ref['Date'] + pd.to_timedelta(7, unit='d')

out = (sales.conditional_join(ref,
      ('Date', 'end', '<='),
      ('Date', 'start', '>='),
      ('Fruit', 'Fruit', '=='),
     how='right')
      .drop([('left','Fruit'), ('left','Date')], axis=1)
      .droplevel(0, axis=1)
      .groupby(['Fruit', 'Date'], as_index=False)['Quantity'].sum())
print (out)
     Fruit       Date  Quantity
0   apples 2023-06-27      16.0
1   apples 2023-07-25      36.0
2  bananas 2023-10-25      16.0
3  bananas 2023-12-27       0.0
4  oranges 2023-04-14       0.0
5  oranges 2023-07-13       0.0
6  oranges 2023-09-17      18.0
7  oranges 2023-10-05       0.0
8    pears 2023-07-08       0.0

Python相关问答推荐

在编写要Excel的数据透视框架时修复标题行

Pydantic:如何将对象列表表示为dict(将列表序列化为dict)

替换字符串中的多个重叠子字符串

Polars LazyFrame在收集后未返回指定的模式顺序

Python 约束无法解决n皇后之谜

删除所有列值,但判断是否存在任何二元组

Pandas 都是(),但有一个门槛

Pandas - groupby字符串字段并按时间范围 Select

如何让Flask 中的请求标签发挥作用

加速Python循环

如何将一个动态分配的C数组转换为Numpy数组,并在C扩展模块中返回给Python

如何在WSL2中更新Python到最新版本(3.12.2)?

python中字符串的条件替换

如何保持服务器发送的事件连接活动?

合并帧,但不按合并键排序

在Python 3中,如何让客户端打开一个套接字到服务器,发送一行JSON编码的数据,读回一行JSON编码的数据,然后继续?

在不同的帧B中判断帧A中的子字符串,每个帧的大小不同

Pandas:计算中间时间条目的总时间增量

pandas fill和bfill基于另一列中的条件

如何过滤组s最大和最小行使用`transform`'