【问题标题】:Create a time series that sums data on each day D, if D is between the start date and the end date如果 D 在开始日期和结束日期之间,则创建一个时间序列,对每天 D 的数据求和
【发布时间】:2021-11-26 16:20:19
【问题描述】:

我的原始数据是一个包含 列描述旅程的数据框:数量开始日期结束日期。我的目标是创建一个具有每日索引和一个单列的新数据框,该列显示每天“在路上”的旅程的数量总和,即如果天 > 开始日期和天 for 循环来实现这一点,该循环每天使用 mask 过滤数据,然后求和。我还没有成功,但我认为实际上可能有更好的方法?下面是我对一些虚拟数据的尝试......

data = [[10, '2020-03-02', '2020-03-27'],
        [18, '2020-03-06', '2020-03-10'],
        [21, '2020-03-20', '2020-05-02'],
        [33, '2020-01-02', '2020-03-01']]
columns = ['quantity', 'startdate', 'enddate']
index = [1,2,3,4]
df = pd.DataFrame(data,index,columns)

index2 = pd.date_range(start='2020-01-01', end='2020-06-01', freq='D')
df2 = pd.DataFrame(0,index2,'quantities')
for t in index2:
    mask = (df['start']<t) & (df['end']>t)
    df2['quantities'] = df[mask]['quantity'].sum()

【问题讨论】:

  • 什么是quantities?您的第二个数据框未正确共享。另外,请添加您预期的数据框输出

标签: python pandas pandas-groupby


【解决方案1】:

也许您可以为每条记录创建日期范围,然后进行分解和分组:

data = [[10, '2020-03-02', '2020-03-27'],
        [18, '2020-03-06', '2020-03-10'],
        [21, '2020-03-20', '2020-05-02'],
        [33, '2020-01-02', '2020-03-01']]
columns = ['quantity', 'startdate', 'enddate']
index = [1,2,3,4]
df = pd.DataFrame(data,index,columns)

df['range'] = df.apply(lambda x: pd.date_range(x['startdate'],x['enddate'],freq='D'), axis=1)
df = df.explode('range')
df.groupby('range')['quantity'].sum()

【讨论】:

    【解决方案2】:

    您的数据描述了一个阶跃函数,即在 3 月 2 日(午夜)它增加了 10 的值,在 3 月 27 日(午夜)它减少了 10。

    此解决方案使用一个名为 staircase 的包,它基于 pandasnumpy 构建,用于处理(数学)阶跃函数。

    设置

    data = [[10, '2020-03-02', '2020-03-27'],
            [18, '2020-03-06', '2020-03-10'],
            [21, '2020-03-20', '2020-05-02'],
            [33, '2020-01-02', '2020-03-01']]
    columns = ['quantity', 'startdate', 'enddate']
    index = [1,2,3,4]
    df = pd.DataFrame(data,index,columns)
    dates = pd.date_range(start='2020-01-01', end='2020-06-01', freq='D')
    
    df["startdate"] = pd.to_datetime(df["startdate"])
    df["enddate"] = pd.to_datetime(df["enddate"])
    

    解决方案

    创建一个staircase.Stairs 对象(它是staircase,因为pandas.Seriespandas),它代表一个阶梯函数。就像传递开始时间、结束时间和值一样简单,因为您的数据在 pandas.Dataframe 中,可以通过传递列名来完成

    import staircase as sc
    sf = sc.Stairs(frame=df, start="startdate", end="enddate", value="quantity")
    

    默认情况下,阶跃函数将由左闭区间组成。 阶梯函数可以做很多事情,包括绘图

    sf.plot(style="hlines")
    

    如果您只想在每天开始时获取值,那么您可以像这样对 step 函数进行采样

    sf(dates, include_index=True)
    

    结果将是一个由您的日期范围索引的pandas.Series

    2020-01-01     0
    2020-01-02    33
    2020-01-03    33
    2020-01-04    33
    2020-01-05    33
                ..
    2020-05-28     0
    2020-05-29     0
    2020-05-30     0
    2020-05-31     0
    2020-06-01     0
    Freq: D, Length: 153, dtype: int64
    

    使用slicing and integrating 可以为您的问题提供更通用的解决方案,包括任何日期时间(不仅仅是午夜)的开始和结束时间以及任意分档。

    【讨论】:

      猜你喜欢
      • 2018-10-16
      • 1970-01-01
      • 2021-06-20
      • 2019-05-19
      • 1970-01-01
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多