pandas 将时间戳分桶到 TimeGrouper 频率组中

pandas bucket timestamp into TimeGrouper frequency group

我在 pandas 中有一个带有 DateTime 索引的数据框。 当使用 time grouper 对其进行分组时:pd.Grouper(freq='360Min'),如何将此结果加入到原始时间戳中? IE。 equijoin timestamp=bucket 不起作用? 有方便的功能吗? 应该使用 asof 连接吗? 或者我是否必须手动提取小时数然后尝试匹配它?

示例:

来源

import pandas as pd
df = pd.DataFrame(
   {
       "Publish date": [
            pd.Timestamp("2000-01-02"),
            pd.Timestamp("2000-01-02"),
            pd.Timestamp("2000-01-09"),
            pd.Timestamp("2000-01-16")
        ],
        "ID": [0, 1, 2, 3],
        "Price": [10, 20, 30, 40]
    }
)

给出:

  Publish date  ID  Price
0   2000-01-02   0     10
1   2000-01-02   1     20
2   2000-01-09   2     30
3   2000-01-16   3     40

我想以任意频率(不仅是月、日、小时)执行聚合,假设 1

month.

agg_result = df.groupby(pd.Grouper(key="Publish date", freq="1M")).agg([pd.Series.mean, pd.Series.median]).reset_index()
agg_result.columns = ['_'.join(col).strip() for col in agg_result.columns.values]
agg_result.columns = ['Publish date month', 'ID_mean', 'ID_median', 'Price_mean', 'Price_median']
print(agg_result)
Publish date month  ID_mean  ID_median  Price_mean  Price_median
0         2000-01-31      1.5        1.5          25            25

如何确保等值连接再次起作用? IE。使用相同的任意频率将原始时间戳转换为拟合桶?

即在例子的代码中描述,我如何得到:

agg_result['Publish date month'] = agg_result['Publish date'].apply(magic transform to same frequency bucket)
df.merge(agg_result, on['Publish date month'])

要工作,即将转换定义到正确的存储桶?

编辑:

确定每组对应原始值的最简单方法应该是:

gb = df.groupby(pd.Grouper(key="Publish date", freq="1M"))
dict(list(gb['Publish date']))

然后您可以使用它来将任何信息连接回原始 table。


你能加入两个中间列吗?

df['Publish date'].dt.month

df.groupby(pd.Grouper(key="Publish date", freq="1M")).agg([pd.Series.mean, pd.Series.median]).index.month

像这样

results =  df.groupby(pd.Grouper(key="Publish date", freq="1M")).agg([pd.Series.mean, pd.Series.median])

results.columns = ['-'.join(col[::-1]).strip() for col in results.columns]

df['month'] = df['Publish date'].dt.month

results['month'] = results.index.month
results.merge(df)

我会使用 Groupby.transform 方法:

import pandas as pd
df = pd.DataFrame(
   {
       "Publish date": [
            pd.Timestamp("2000-01-02"),
            pd.Timestamp("2000-01-02"),
            pd.Timestamp("2000-01-09"),
            pd.Timestamp("2000-01-16")
        ],
        "ID": [0, 1, 2, 3],
        "Price": [10, 20, 30, 40]
    }
)

g = df.groupby(pd.Grouper(key="Publish date", freq="1M"))

(
  df.join(g.transform('mean'), rsuffix='_mean')
    .join(g.transform('median'), rsuffix='_median')
)

还有那个 returns:

  Publish date  ID  Price  ID_mean  Price_mean  ID_median  Price_median
0   2000-01-02   0     10      1.5          25        1.5            25
1   2000-01-02   1     20      1.5          25        1.5            25
2   2000-01-09   2     30      1.5          25        1.5            25
3   2000-01-16   3     40      1.5          25        1.5            25

您也可以使用 pandas.concat 代替 DataFrame.join:

methods = ['mean', 'median', 'std', 'min', 'max']

pd.concat([
    df, *[g.transform(m).add_suffix(f'_{m}') for m in methods]
], axis='columns')

这给你:

  Publish date  ID  Price  ID_mean  Price_mean  ID_median  Price_median    ID_std  Price_std  ID_min  Price_min  ID_max  Price_max
0   2000-01-02   0     10      1.5          25        1.5            25  1.290994  12.909944       0         10       3         40
1   2000-01-02   1     20      1.5          25        1.5            25  1.290994  12.909944       0         10       3         40
2   2000-01-09   2     30      1.5          25        1.5            25  1.290994  12.909944       0         10       3         40
3   2000-01-16   3     40      1.5          25        1.5            25  1.290994  12.909944       0         10       3         40