首页 > 解决方案 > 使用时间滚动计数熊猫分类变量

问题描述

我有一个看起来像这样的数据框:

Datetime   | Category | ID
--------------------------
2020-01-30 | A        | 1
2020-02-01 | B        | 1
2020-02-02 | A        | 1
2020-02-20 | A        | 1
2020-01-28 | B        | 2
2020-01-29 | C        | 2
2020-01-30 | C        | 2
2020-01-31 | D        | 2
2020-02-01 | D        | 2
2020-02-02 | D        | 2
2020-02-03 | C        | 2

我想在该行的 1 周窗口内获取每个 ID 的前 2 个最常见的类别(不包括当前行)。熊猫有可能吗?我试图做 .rolling 和 .value_counts 但它似乎不起作用。谢谢!

下面是我想得到的数据框:

Datetime   | Category | ID
--------------------------
2020-01-30 | NaN      | 1
2020-02-01 | [A, ""]  | 1
2020-02-02 | [A, B]   | 1
2020-02-20 | NaN      | 1
2020-01-28 | Nan      | 2
2020-01-29 | [B,""]   | 2
2020-01-30 | [B,C]    | 2
2020-01-31 | [B,C]    | 2
2020-02-01 | [C,D]    | 2
2020-02-02 | [C,D]    | 2
2020-02-03 | [C,D]    | 2

谢谢!

编辑 pd.get_dummies 答案很好,但由于我的数据集很大,它效率不高。如果有人对此有有效的解决方案,将不胜感激!谢谢!

标签: pythonpandasrolling-computation

解决方案


您可以使用resample()而不是rolling(),因为您的时间索引频率是每天,并且您想要每周统计信息,所以请尝试以下操作:

df.groupby('ID').resample('1w').apply(lambda s: s.value_counts().head(2))

请注意,这仅适用于apply()将数据剥离为的 Pandas 版本pd.Series,而不是np.arrays. 此外,如果您的数据框中有更多列,则可能需要在 lambda 函数中指定列名,即:

df.groupby('ID').resample('1w').apply(lambda s: s['Category'].value_counts().head(2))

如果您需要排除窗口中的第一行,请使用iloc[]切片:

df.groupby('ID').resample('1w').apply(lambda s: s['Category'].iloc[1:].value_counts().head(2))

推荐阅读