Pandas 的整数索引重采样等价物

Posted

技术标签:

【中文标题】Pandas 的整数索引重采样等价物【英文标题】:Pandas' equivalent of resample for integer index 【发布时间】:2016-09-20 15:29:14 【问题描述】:

我正在寻找与 resample 方法等效的 pandas 方法,该方法不是 DatetimeIndex 而是整数数组,甚至可能是浮点数。

我知道在某些情况下(例如this one),resample 方法可以很容易地被重新索引和插值替换,但在某些情况下(我认为)它不能。

例如,如果我有

df = pd.DataFrame(np.random.randn(10,2))
withdates = df.set_index(pd.date_range('2012-01-01', periods=10))
withdates.resample('5D', np.std)

这给了我

                   0         1
2012-01-01  1.184582  0.492113
2012-01-06  0.533134  0.982562

但我无法使用df 和重新采样产生相同的结果。所以我正在寻找可以作为的东西

 df.resample(5, np.std)

那会给我

          0         1
0  1.184582  0.492113
5  0.533134  0.982562

这样的方法存在吗?我能够创建此方法的唯一方法是手动将 df 分离为较小的数据帧,应用 np.std 然后将所有内容连接回来,我觉得这很慢而且一点也不聪明。

干杯

【问题讨论】:

【参考方案1】:

设置

import pandas as pd
import numpy as np

np.random.seed([3,1415])
df = pd.DataFrame(np.random.rand(20, 2), columns=['A', 'B'])

您需要自己创建要分组的标签。我会使用:

(df.index.to_series() / 5).astype(int)

为您获取一系列值,例如 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, ...] 然后在 groupby 中使用它

您还需要为新数据框指定索引。我会使用:

df.index[4::5]

获取从第 5 个位置开始的当前索引(因此是 4)以及之后的每第 5 个位置。它看起来像[4, 9, 14, 19]。我可以使用df.index[::5] 来获得起始位置,但我选择了结束位置。

解决方案

# assign as variable because I'm going to use it more than once.
s = (df.index.to_series() / 5).astype(int)

df.groupby(s).std().set_index(s.index[4::5])

看起来像:

           A         B
4   0.198019  0.320451
9   0.329750  0.408232
14  0.293297  0.223991
19  0.095633  0.376390

其他注意事项

这相当于下采样。我们还没有解决抽样问题。

要通过更频繁的方式从我们生成的内容返回到数据帧索引,我们可以像这样使用reindex

# assign what we've done above to df_down
df_down = df.groupby(s).std().set_index(s.index[4::5])

df_up = df_down.reindex(range(20)).bfill()

看起来像:

           A         B
0   0.198019  0.320451
1   0.198019  0.320451
2   0.198019  0.320451
3   0.198019  0.320451
4   0.198019  0.320451
5   0.329750  0.408232
6   0.329750  0.408232
7   0.329750  0.408232
8   0.329750  0.408232
9   0.329750  0.408232
10  0.293297  0.223991
11  0.293297  0.223991
12  0.293297  0.223991
13  0.293297  0.223991
14  0.293297  0.223991
15  0.095633  0.376390
16  0.095633  0.376390
17  0.095633  0.376390
18  0.095633  0.376390
19  0.095633  0.376390

我们还可以使用其他东西来reindex,比如range(0, 20, 2),将样本上采样到偶数索引。

【讨论】:

不错的解决方案。我并不太担心上采样,但现在你这样做了,我想知道重新索引。也许用浮点数重新索引它会更好(比如np.linspace(start, end, number_of_indexes))。这值得一个 github 问题作为改进吗? 我刚在花车上试过...不好。看到这正式化会很有趣。更重要的是,我是否正确解释了您的问题?我成功回答了吗? 是的,别担心,我会马上接受你的回答。实际上,您启发了我想出自己的答案,我只是为了社区而将其发布。它更长,但它可能更强大。我会在一秒钟内发布它。我们将不胜感激您的想法。 这对于示例数据非常有用。但是如果我在我的真实数据上运行它,此时s.index[4::5] 我遇到了麻烦。我不能从任意点开始,只有几个,然后我得到一个ValueError: Lengths mismatch. 我不明白为什么。我想每 100 次对数据进行二次抽样。 s.index[13::100] 工作正常,但 s.index[14::100] 和任何更高的都会引发错误。我的维度在哪里丢失了?【参考方案2】:

另类,这是可以做的一件事

def resample(df, rule, how=None, **kwargs):
    import pandas as pd
    if how==None:
        import numpy as np
        how = np.mean

    if isinstance(df.index, pd.DatetimeIndex) and isinstance(rule, str):
        return df.resample(rule, how, **kwargs)
    else:
        idx, bins = pd.cut(df.index, range(df.index[0], df.index[-1]+2, rule), right=False, retbins=True)
        aux = df.groupby(idx).apply(how)
        aux = aux.set_index(bins[:-1])
        return aux

【讨论】:

看起来不错,但我认为idx和bins在这里交换(即pd.cut的输出是bins,idx,然后groupby应该是bins,set_index和index)【参考方案3】:

@piSquared 解决方案非常好,但我不喜欢在重新索引时手动选择索引。

这也适用于每种下采样(浮动索引),并自动选择每个范围内索引的平均值:

df = pd.DataFrame(index = np.random.rand(20)*30, data=np.random.rand(20, 2), columns=['A', 'B'])
df.index.name = 'crazy_index'

s = (df.index.to_series() / 10).astype(int)

现在您可以随意在每个子组中选择要计算的函数:

# calculate std() in each group
df.groupby(s).mean().set_index( s.groupby(s).apply(lambda x: np.mean(x.index)) )

                    A         B
crazy_index
3.667539     0.276986  0.317642
14.275074    0.248700  0.372551
25.054042    0.254860  0.297586

# calculate median() in each group
df.groupby(s).median().set_index( s.groupby(s).apply(lambda x: np.mean(x.index)) )
Out[38]:
                    A         B
crazy_index
3.667539     0.454654  0.521649
14.275074    0.451265  0.490125
25.054042    0.489326  0.622781

编辑:s 索引中有一些错误,现在它是正确的并且可以工作。

【讨论】:

以上是关于Pandas 的整数索引重采样等价物的主要内容,如果未能解决你的问题,请参考以下文章

pandas的resample重采样

如何使用 Pandas 同时应用重采样和分组?

Pandas 重采样的替代方案

python pandas重采样计数和总和

没有重采样的时间序列的 Pandas 子集

pandas resample 重采样