【问题标题】:How to properly aggregate timeseries data using Pandas into DataFrames instead of Series?如何使用 Pandas 将时间序列数据正确聚合到 DataFrame 而不是 Series?
【发布时间】:2021-11-20 13:20:02
【问题描述】:

这来自《实用时间序列分析》一书的第 2 章,因为它是从一开始就开始的,所以我试图一步一步地跟随。我写了一个笔记本显示错误here交易如下。

我们正在尝试每周汇总信息,然后将来自两个来源的信息合并起来:Weekly user information about how many emails were openactual user donation,包括捐赠金额和捐赠时间戳。

我们首先为电子邮件数据集创建一个完整的 idx,为缺失的数据填充 0:

complete_idx = pd.MultiIndex.from_product((set(emails.week),
                                      set(emails.user)))
all_email = emails.set_index(['week', 'user']).reindex(complete_idx, fill_value = 0).reset_index()
all_email.columns = ['week', 'member', 'EmailsOpened']

然后删除每个系列的尾随零。

cutoff_dates = emails.groupby('user').week.agg(['min', 'max']).reset_index()
cutoff_dates = cutoff_dates.reset_index()
for _, row in cutoff_dates.iterrows(): 
  member     = row['user']
  start_date = row['min']
  end_date   = row['max'] 
  all_email.drop(all_email[all_email.member == member]
                 [all_email.week < start_date].index, inplace=True) 
  all_email.drop(all_email[all_email.member == member]
                 [all_email.week > end_date].index, inplace=True)

到目前为止一切顺利。当我们查看捐款时,问题就开始了。最初,我们使用时间戳设置了一个适当的索引,以便稍后进行分组并应用 lambda 函数将信息重新采样为几周,并对每周的数量求和

donations.timestamp = pd.to_datetime(donations.timestamp)
donations.set_index('timestamp', inplace = True)
agg_donations = donations.groupby('user').apply(lambda df: df.amount.resample("W-MON").sum().dropna())

奇怪的是,我们重新采样的结果是一个系列,而不是一个数据帧,虽然这似乎不是问题,但本书的以下示例尝试合并数据,afik,它正在执行 SQL-JOIN使用用户和时间字段作为键:

for member, member_email in all_email.groupby('member'):
  member_donations = agg_donations[agg_donations.member == member]

  member_donations.set_index('timestamp', inplace = True) 
  member_email.set_index    ('week', inplace = True) 

  member_email = all_email[all_email.member == member]
  member_email.sort_values('week').set_index('week') 

  df = pd.merge(member_email, member_donations, how = 'left', 
                              left_index = True, 
                              right_index = True)
  df.fillna(0) 

  df['member'] = df.member_x 
  merged_df = merged_df.append(df.reset_index()[['member', 'week', 'emailsOpened', 'amount']])

第一个问题是您不能像在这种情况下使用数据框 member_donations = agg_donations[agg_donations.member == member] 那样使用括号来过滤系列数据,我们可以通过直接访问每个成员 agg_donations[member] 轻松解决此问题尝试设置索引,失败,因为Series对象没有属性'set_index',这意味着在进入for循环之前我应该​​有一个DataFrame。

为什么agg_donations = donations.groupby('user').apply(lambda df: df.amount.resample("W-MON").sum().dropna()) 返回一个系列?如何将其转换为具有适当列的 DataFrame?

结果应该是用户每周打开的电子邮件数量与该周捐赠的相应数量。

【问题讨论】:

    标签: python pandas dataframe merge time-series


    【解决方案1】:

    盲人 Pandas 一直是一场冒险,但是,嘿,我想我到了应该去的地方。

    首先是将 agg_donations 系列重新创建为适当的 DataFrame,其中 DateTime 将是索引、成员和捐赠列。因此,我将首先通过在适当的轴上取消堆叠系列来选择用户列:

    userlist = list(agg_donations.unstack().axes[0])
    

    有了这个,我可以遍历所有用户,从原始数据框中提取信息,添加成员列并将所有内容附加到新数据框:

    df_agg_don = pd.DataFrame()
    for u in userlist:
      dict1 = agg_donations[u]
      temp_df = pd.DataFrame(agg_donations[u])
      temp_df['member'] = u
      df_agg_don = df_agg_don.append(temp_df)
    

    现在合并循环将发生一些变化以反映这些变化:

    member_donations = df_agg_don[df_agg_don.member == member]
    member_email = all_email[all_email.member == member]
    

    我们仍然可以通过使用它来获取与每个成员相关的部分,但是 member_email 需要一些与其索引相关的修复,以便连接正常工作。

    member_email.set_index('week', inplace = True) 
    member_email.index = pd.to_datetime(member_email.index)
    

    合并后我们还要对数据进行排序

      df = pd.merge(member_email, member_donations, how = 'left', 
                                  left_index = True, 
                                  right_index = True)
      df = df.sort_values('week').fillna(0) 
    

    在将所有内容添加到 merge_df 之前

    df['member'] = df.member_x 
    merged_df = merged_df.append(df.reset_index()[['member', 'week', 'EmailsOpened', 'amount']])
    

    下一个代码可以从书中复制并执行,因此它提供了下一页下一个示例中的正确值。

    df = merged_df[merged_df.member == 998]
    df['target'] = df.amount.shift(1)
    df = df.fillna(0)
    print(df.sort_values('week'))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-22
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2023-01-23
      • 2019-06-02
      • 1970-01-01
      • 2016-12-28
      相关资源
      最近更新 更多