【问题标题】:Iterate through range of dates and find the sum in each group遍历日期范围并找到每个组中的总和
【发布时间】:2021-04-11 14:11:32
【问题描述】:

我有一个如下所示的数据框:

    ID    Date        Volume      Sales
0   1   2019-01-01  3.333333    1.333333
1   1   2019-02-01  3.333333    1.333333
2   1   2019-03-01  3.333333    1.333333
3   1   2019-04-01  2.666667    2.000000
4   1   2019-05-01  2.666667    2.000000
5   1   2019-06-01  2.666667    2.000000
6   2   2019-01-01  2.000000    2.666667
7   2   2019-02-01  2.000000    2.666667
8   2   2019-03-01  2.000000    2.666667
9   2   2019-04-01  1.333333    3.333333
10  2   2019-05-01  1.333333    3.333333
11  2   2019-06-01  1.333333    3.333333

我想总结每个组 (ID) 中一组日期的数据(数量和销售额)。

从 2019-01-01 到 2019-04-01 和 2019-02-01 到 2019-05-01

我相信这可以使用 for 循环来完成,但很难获得预期的结果

注意:问题可能措辞不佳。如果您有任何其他问题,请发表评论

异常输出:

ID         Date                 Volume      Sales
1   2019-01-01 to 2019-04-01    12.67        6
1   2019-02-01 to 2019-05-01    12           6.66
2   2019-01-01 to 2019-04-01    7.33         11.33
2   2019-02-01 to 2019-05-01    6.66         12

没有必要在输出中包含日期列

【问题讨论】:

    标签: python pandas dataframe numpy datetime


    【解决方案1】:
    df["group_1"] = (df["Date"] >= pd.Timestamp("2019-01-01")) & (
        df["Date"] <= pd.Timestamp("2019-04-01")
    )
    df["group_2"] = (df["Date"] >= pd.Timestamp("2019-02-01")) & (
        df["Date"] <= pd.Timestamp("2019-05-01")
    )
    
    g1 = df[df["group_1"] == True].groupby("ID")
    g2 = df[df["group_2"] == True].groupby("ID")
    
    df = pd.concat(
        [
            g1.agg({"Volume": "sum", "Sales": "sum"}),
            g2.agg({"Volume": "sum", "Sales": "sum"}),
        ]
    ).sort_index()
    
    print(df)
    

    打印:

           Volume      Sales
    ID                      
    1   12.666666   5.999999
    1   12.000000   6.666666
    2    7.333333  11.333334
    2    6.666666  12.000000
    

    如果你想要Date 专栏:

    ...
    
    df = pd.concat(
        [
            g1.agg({"Volume": "sum", "Sales": "sum"}).assign(
                Date="2019-01-01 to 2019-04-01"
            ),
            g2.agg({"Volume": "sum", "Sales": "sum"}).assign(
                Date="2019-02-01 to 2019-05-01"
            ),
        ]
    ).sort_index()
    

    打印:

           Volume      Sales                      Date
    ID                                                
    1   12.666666   5.999999  2019-01-01 to 2019-04-01
    1   12.000000   6.666666  2019-02-01 to 2019-05-01
    2    7.333333  11.333334  2019-01-01 to 2019-04-01
    2    6.666666  12.000000  2019-02-01 to 2019-05-01
    

    编辑:概括:

    df["Date"] = pd.to_datetime(df["Date"])
    
    # add dates to this group:
    groups = [
        [pd.Timestamp("2019-01-01"), pd.Timestamp("2019-04-01")],
        [pd.Timestamp("2019-02-01"), pd.Timestamp("2019-05-01")],
        [pd.Timestamp("2019-03-01"), pd.Timestamp("2019-06-01")],
    ]
    
    grouped = []
    for i, (t1, t2) in enumerate(groups, 1):
        df["group_{}".format(i)] = (df["Date"] >= t1) & (df["Date"] <= t2)
        grouped.append(
            df[df["group_{}".format(i)] == True]
            .groupby("ID")
            .agg({"Volume": "sum", "Sales": "sum"})
            .assign(Date="{} to {}".format(t1.date(), t2.date()))
        )
    
    df = pd.concat(grouped).sort_index()
    
    print(df)
    

    打印:

           Volume      Sales                      Date
    ID                                                
    1   12.666666   5.999999  2019-01-01 to 2019-04-01
    1   12.000000   6.666666  2019-02-01 to 2019-05-01
    1   11.333334   7.333333  2019-03-01 to 2019-06-01
    2    7.333333  11.333334  2019-01-01 to 2019-04-01
    2    6.666666  12.000000  2019-02-01 to 2019-05-01
    2    5.999999  12.666666  2019-03-01 to 2019-06-01
    

    【讨论】:

    • 感谢您的回复。有没有办法编写这段代码,可以自动确定日期范围的数量。例如,如果我添加另一个日期范围。我不必添加 group_3。
    【解决方案2】:

    您可以在dts列表中将日期范围设置为(start, end)元组:

    dts = [('2019-01-01', '2019-04-01'), ('2019-02-01', '2019-05-01')]
    
    df_out = pd.concat([
        (df
             .loc[df['Date'].between(dt_start, dt_end)]   # filter dates in range
             .groupby('ID', as_index=False).sum()         # calculate sum
             .assign(Date=f'{dt_start} to {dt_end}'))     # set `Dates` values
      for (dt_start, dt_end) in dts], ignore_index=True)[df.columns]
    
    df_out
    

    输出:

       ID                      Date     Volume      Sales
    0   1  2019-01-01 to 2019-04-01  12.666666   5.999999
    1   2  2019-01-01 to 2019-04-01   7.333333  11.333334
    2   1  2019-02-01 to 2019-05-01  12.000000   6.666666
    3   2  2019-02-01 to 2019-05-01   6.666666  12.000000
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 1970-01-01
      • 2011-05-30
      相关资源
      最近更新 更多