pandas panda滚动组按滚动组的agg“大小”(而不是“计数”)

z5btuh9x  于 2023-01-24  发布在  其他
关注(0)|答案(3)|浏览(147)

可以执行

df.groupby.rolling.agg({'any_df_col': 'count'})

但是agg号的怎么样?
'count'将生成一个序列,其中包含与groupby条件(1,1,1,2,3 ...)匹配的行的'running count',但我想知道,对于所有这些行,在这种情况下与groupby(so,1,1,3,3,3)匹配的总行数是多少。
通常我认为Pandas是通过大小而不是数量来实现的。
这个代码可以说明。
x一个一个一个一个x一个一个二个一个x一个一个三个一个
我想要的输出是得到组的大小......如下:

type
value time_ref
1     2023-01-01 00:30:00   2
      2023-01-01 01:00:00   2
2     2023-01-01 00:30:00   1
10    2023-01-01 02:00:00   3
      2023-01-01 02:15:00   3
      2023-01-01 02:16:00   3
      2023-01-01 04:00:00   1

我想不出一种方法来做我需要的事情而不使用滚动功能,因为我的数据的相关窗口不是由日历时间而是由事件本身的时间确定的...如果这个假设是错误的,我可以这样做,并在不使用滚动的情况下获得一个"大小",这是可以的,但据我所知,我必须使用滚动,因为事件的time_ref是与后续行分组的重要因素,而不是纯粹的日历时间。
谢谢。

m528fe3b

m528fe3b1#

我没有完全理解您的问题,您似乎希望type列是给定值每增加1小时的行数......但如果是这种情况,您希望的输出是不正确的,应该是:

value time_ref              type
1     2023-01-01 00:30:00   1  # <- not 2 here (1 in 0-hr, 1 in 1-hr window)
      2023-01-01 01:00:00   1  # <- same here
2     2023-01-01 00:30:00   1  # rest is ok....
...

如果这是正确的,那么,开始:

df = pd.DataFrame({
    'time_ref': [
        dt.datetime(2023, 1, 1, 0, 30),
        dt.datetime(2023, 1, 1, 0, 30),
        dt.datetime(2023, 1, 1, 1),
        dt.datetime(2023, 1, 1, 2),
        dt.datetime(2023, 1, 1, 2, 15),
        dt.datetime(2023, 1, 1, 2, 16),
        dt.datetime(2023, 1, 1, 4)],
    'value': [1, 2, 1, 10, 10, 10, 10]})

...只需添加一个小时列:

df['hour'] = df.time_ref.dt.hour

并在其上聚集value

tmp = (
    df.groupby(['value', 'hour'])
    .agg('count')
    .reset_index()
    .rename(columns={'time_ref': 'type'}))

它提供给您:

value   hour type
0   1       0    1
1   1       1    1
2   2       0    1
3   10      2    3
4   10      4    1

...您可以将其连接回原始df:

res = df.merge(tmp, how='left', on=['value', 'hour'])
time_ref                value hour  type
0   2023-01-01 00:30:00     1     0     1
1   2023-01-01 00:30:00     2     0     1
2   2023-01-01 01:00:00     1     1     1
3   2023-01-01 02:00:00     10    2     3
4   2023-01-01 02:15:00     10    2     3
5   2023-01-01 02:16:00     10    2     3
6   2023-01-01 04:00:00     10    4     1

如果这不是你想要的,你可以澄清你的问题。

j5fpnvbx

j5fpnvbx2#

啊......谢谢你的澄清。我现在明白问题所在了。我试过滚动,但也找不到一种方法让它工作......但这里有一个替代方法:

df = pd.DataFrame({
    'time_ref': [
        dt.datetime(2023, 1, 1, 0, 30),
        dt.datetime(2023, 1, 1, 0, 30),
        dt.datetime(2023, 1, 1, 1),
        dt.datetime(2023, 1, 1, 2),
        dt.datetime(2023, 1, 1, 2, 15),
        dt.datetime(2023, 1, 1, 2, 16),
        dt.datetime(2023, 1, 1, 4)],
    'value': [1, 2, 1, 10, 10, 10, 10]})
df.index = df.time_ref

value_start = df.groupby('value').agg(min)

df['hrs_since_group_start'] = df.apply(
    lambda row: row.time_ref - value_start.loc[row.value, 'time_ref'],
    axis=1
).view(int) / 1_000_000_000 / 60 // 60

.view(int)将时间增量更改为纳秒。因此/ 1_000_000_000 / 60将其更改为自第一组以来的分钟数,// 60将其更改为自第一组以来的整小时数。)

group_hourly_counts = (
    df.groupby(['value', 'hrs_since_group_start'])
    .agg('count')
    .reset_index()
    .rename(columns={'time_ref': 'type'}))

res = (
    df.merge(
        group_hourly_counts,
        how='left',
        on=['value', 'hrs_since_group_start'])
    .drop(columns='hrs_since_group_start'))

res

time_ref                value type
0   2023-01-01 00:30:00     1     2
1   2023-01-01 00:30:00     2     1
2   2023-01-01 01:00:00     1     2
3   2023-01-01 02:00:00     10    3
4   2023-01-01 02:15:00     10    3
5   2023-01-01 02:16:00     10    3
6   2023-01-01 04:00:00     10    1

......不过,更熟悉rolling功能的人可能会为您找到更简单的解决方案:)

0qx6xfy6

0qx6xfy63#

如果.rollingcount组合不起作用,那么我不认为这是一个真正的“rolling-问题”。您可以尝试以下方法(我认为这与Damians 2. answer类似):

df = df.assign(
    hours=df["time_ref"].sub(df.groupby("value")["time_ref"].transform("first"))
          .dt.seconds.floordiv(3_600),
    type=lambda df: df.groupby(["value", "hours"]).transform("size")
).drop(columns="hours").set_index(["value", "time_ref"]).sort_index()

样品结果:

type
value time_ref                 
1     2023-01-01 00:30:00     2
      2023-01-01 01:00:00     2
2     2023-01-01 00:30:00     1
10    2023-01-01 02:00:00     3
      2023-01-01 02:15:00     3
      2023-01-01 02:16:00     3
      2023-01-01 04:00:00     1

相关问题