基于另一个DataFrame的日期构建新的Pandas DataFrame

5fjcxozz  于 2023-06-20  发布在  其他
关注(0)|答案(2)|浏览(99)

我的标题不是很好,因为我很难表达我的问题。基本上,我有一个DateFrame,其中的事务数据由几个DateTime列和一个value列组成。我需要对日期应用过滤器,并在新的DataFrame中对结果值求和。
下面是我的DateFrame df的简化版本:

Sched Week  Ship Week   Ready Week  vals
0   2021-01-04  2021-01-11  2021-01-04  10
1   2021-01-04  2021-01-11  2021-01-04  10
2   2021-01-04  2021-01-04  2021-01-04  2
3   2021-01-07  2021-01-18  2021-01-04  9
4   2021-01-12  2021-01-18  2021-01-11  1
5   2021-01-13  2021-01-11  2021-01-11  6
6   2021-01-13  2021-01-11  2021-01-11  4
7   2021-01-13  2021-01-25  2021-01-11  8
8   2021-01-15  2021-01-25  2021-01-18  4
9   2021-01-19  2021-01-25  2021-01-18  5
10  2021-01-19  2021-01-25  2021-01-18  6
11  2021-01-21  2021-01-25  2021-01-18  10
12  2021-01-21  2021-01-25  2021-01-18  6

根据df中的值,我想创建的新DataFrame df_result应该如下所示。这个DataFrame中的Sched Week列就是df['Sched Week'].unique(),foo是满足以下条件的行的df['values']的和。

Sched Week  foo
0   2021-01-04  20
1   2021-01-07  29
2   2021-01-12  10
3   2021-01-13  18
4   2021-01-15  18
5   2021-01-19  23
6   2021-01-21  39

下面是生成新DataFrame的基本逻辑:

df['Sched Week'] <= df_result['Sched Week'] &
df['Ship Week'] > df_result['Sched Week'] &
df['Ready Week'] <= df_result['Sched Week']

需要对新df_result DataFrame中的每一行执行此测试,并将值相加。
因此,索引0处的20是原始df中索引0和1处的值之和,因为这些行满足2021 - 01 - 04的条件。
我已经尝试了所有我能想到的布尔掩码和groupby的方法,但到目前为止我所做的一切都没有成功。

    • 编辑**

下面是Excel中的等价物。
单元格J3中的公式为=SUMIFS(F:F,C:C,"<="&I3,D:D,">"&I3,E:E,"<="&I3)
DataFrames represented in Excel

jogvjijk

jogvjijk1#

我不断挖掘,并在这个answer from kait的大量帮助下找到了我的问题的解决方案

def usr(x):
    mask = df['Sched Week'] <= x['Sched Week']
    mask &= df['Ship Week'] > x['Sched Week']
    mask &= df['Ready Week'] <= x['Sched Week']
    x['foo'] = df[mask].vals.sum()
    return x

df_result.apply(lambda x: usr(x), axis=1)
pengsaosao

pengsaosao2#

一种选择是使用不等式连接来获取相关行,在合并回原始数据框架之前,使用groupby对值求和。pyjanitor中的conditional_join为非equi join提供了一个有效的实现--在其背后,它使用二进制搜索,这比遍历每一行(笛卡尔连接)更快/更好--这对于大数据来说变得更加明显:

# pip install pyjanitor
import janitor
import pandas as pd

df = pd.read_clipboard(sep=r'\s{2,}', 
                       engine='python', 
                       parse_dates = ['Sched Week', 'Ship Week', 'Ready Week'])

dff = df['Sched Week'].drop_duplicates()

(df
.conditional_join(
    dff, 
    ('Sched Week', 'Sched Week', '<='), 
    ('Ship Week', 'Sched Week', '>'), 
    ('Ready Week', 'Sched Week', '<='), 
    how = 'right', 
    df_columns='vals')
.groupby('Sched Week', sort=False, as_index=False)
.sum(numeric_only=True)
)
  Sched Week  vals
0 2021-01-04    20
1 2021-01-07    29
2 2021-01-12    10
3 2021-01-13    18
4 2021-01-15    18
5 2021-01-19    23
6 2021-01-21    39

相关问题