【问题标题】:Converting date row to column for last N days将过去 N 天的日期行转换为列
【发布时间】:2018-12-19 17:25:18
【问题描述】:

我想使用诸如一年中的星期、星期几、季节等特征来构建时间序列预测模型。

由于预测会受到最新值的高度影响,我想使用过去 5 天的值作为特征,但是我在为学习准备数据时遇到了问题:

我当前的表格如下所示:

    date        id  score
0   2014-01-01  A   75
1   2014-01-01  B   1
2   2014-01-01  C   2
4   2014-01-02  A   84
5   2014-01-02  B   1
6   2014-01-02  C   3
8   2014-01-03  A   1
9   2014-01-03  B   1
10  2014-01-03  C   1

所以我希望每一行看起来像这样:

    date        id  score  date_1 date_2 date_3 date_4 date-5
10  2014-01-03  A   1      84     75     0      0      0 
 9  2014-01-03  B   1      1      1      0      0      0

Date_1 是 A 的分数,它的日期在 'date' 列的前一天,date_2 是前两天,依此类推...

这样我就可以使用过去 5 天的信息以及与此问题无关的更多特征来预测第二天。 用 0 填充 NaN 值是可以的

【问题讨论】:

    标签: python pandas date group-by row


    【解决方案1】:

    您可以使用groupby(id)shift。在使用以下命令之前,您应该让您的 df 按日期排序:df.sort_values('date')

    for i in range(5):
        df['date_'+str(i+1)] = df.groupby('id')['score'].shift(i+1).fillna(0).astype(int)
    

    使用上述命令产生以下df:

    【讨论】:

    • 不错的答案 - 请参阅下面使用 timedelta 进行移位的示例。
    • 这工作又快又顺利,谢谢。如果我可以用 0 填充每个产品 ID 的缺失日期,则可以实现这一点。你有这样做的想法吗?
    【解决方案2】:

    使用 Timedelta 进行时移

    other answer 正在按数字索引移动。在这种情况下有效,但如果日期中有间隔或日期未排序,它将中断。

    您可以通过将 DataFrame 转换为时间序列,然后将 DataFrame.shift()freq 参数与 pandas.Timedelta 对象一起使用来处理此问题。

    示例数据:

    import pandas as pd
    df = pd.DataFrame({'date': ['2014-01-01'] * 3 +
                               ['2014-01-02'] * 3 +
                               ['2014-01-03'] * 3,
                       'id': ['A', 'B', 'C'] * 3,
                       'score': [75, 1, 2, 84, 1, 3, 1, 1, 1]})
    df.date = pd.to_datetime(df.date)
    df.set_index('date', inplace=True)
    

    ID 意味着我们需要几个循环来将所有内容分开:

    for i in range(5):
        for id in df.id.unique():
            col = 'date_{}'.format(i+1)
            freq = pd.Timedelta('{}d'.format(i+1))
            df.loc[df.id==id, col] = df.loc[df.id==id, 'score'].shift(freq=freq)
        df[col] = df[col].fillna(0).astype(int)
    

    这会产生与此示例中的其他方法相同的输出,但如果您在日期中有一个跳过,它会有所不同。

    输出:

               id  score  date_1  date_2  date_3  date_4  date_5
    date                                                        
    2014-01-01  A     75       0       0       0       0       0
    2014-01-01  B      1       0       0       0       0       0
    2014-01-01  C      2       0       0       0       0       0
    2014-01-02  A     84      75       0       0       0       0
    2014-01-02  B      1       1       0       0       0       0
    2014-01-02  C      3       2       0       0       0       0
    2014-01-03  A      1      84      75       0       0       0
    2014-01-03  B      1       1       1       0       0       0
    2014-01-03  C      1       3       2       0       0       0
    

    【讨论】:

    • 感谢您的笼统回答,因为是的,日期之间存在差距,而且日期不必按索引排序,因此您的愿景很好。但是,当我使用完整表运行确切的代码时,出现错误:“ValueError: cannot reindex from a duplicate axis”
    • 有什么方法可以共享问题中的所有数据,或者更大的提取数据?根据我创建的示例数据,这对我来说效果很好,但如果我们都开始使用相同的数据,那么回答总是更容易。
    • 听起来您的完整表中可能有重复的日期 + id 对(例如,在同一日期有多个 A 条目)。这超出了问题的范围,但在您将'date' 纳入索引之前,将使用.drop_duplicates(['date', 'id']) 进行修复(或者您可能需要执行.groupby(['date', 'id']).score.sum(),具体取决于问题的原因。礼貌地问您如果这确实解决了您的问题,请投票并批准此答案,因为我认为它比使用数字索引更安全。
    • 非常感谢您的帮助。我试过但删除重复项和 groupby.sum 但都没有成功。错误仍然相同。这是完整的数据集:wetransfer.com/downloads/…
    • drop_duplicates() 修复了错误,因为您在数据集中重复了日期/id 对。我怀疑您没有正确执行 drop_duplicates 。加载 DataFrame 后,运行df.drop_duplicates(['date', 'id'], inplace=True),然后所有代码将正常运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多