Python 如何通过2x2平均内核降低数据帧的采样
我正在尝试减少数据帧的采样,以降低粒度。在示例中,我希望减少此数据帧:Python 如何通过2x2平均内核降低数据帧的采样,python,pandas,dataframe,filtering,downsampling,Python,Pandas,Dataframe,Filtering,Downsampling,我正在尝试减少数据帧的采样,以降低粒度。在示例中,我希望减少此数据帧: 1 2 3 4 2 4 3 3 2 2 1 3 3 1 3 2 为此(使用平均值进行下采样以获得2x2数据帧): 有没有一种内置的或有效的方法来做这件事,或者我必须自己写 谢谢您可以使用两次应用的rolling_mean功能,首先对列应用,然后对行应用,然后对结果进行切片: rbs = 2 # row block size cbs = 2 # column block size pd.rolling
1 2 3 4
2 4 3 3
2 2 1 3
3 1 3 2
为此(使用平均值进行下采样以获得2x2数据帧):
有没有一种内置的或有效的方法来做这件事,或者我必须自己写
谢谢您可以使用两次应用的
rolling_mean
功能,首先对列应用,然后对行应用,然后对结果进行切片:
rbs = 2 # row block size
cbs = 2 # column block size
pd.rolling_mean(pd.rolling_mean(df.T, cbs, center=True)[cbs-1::cbs].T,
rbs)[rbs-1::rbs]
这与您想要的结果相同,只是索引不同(但您可以使用.reset\u index(drop=True)
修复此问题):
定时信息:
In [11]: df = pd.DataFrame(np.random.randn(100, 100))
In [12]: %%timeit
pd.rolling_mean(pd.rolling_mean(df.T, 2, center=True)[1::2].T, 2)[1::2]
100 loops, best of 3: 4.75 ms per loop
In [13]: %%timeit
df.groupby(lambda x: x/2).mean().groupby(lambda y: y/2, axis=1).mean()
100 loops, best of 3: 932 µs per loop
因此,它比groupby慢5倍左右,而不是800x:)一个选择是使用groupby两次。一次用于索引:
In [11]: df.groupby(lambda x: x//2).mean()
Out[11]:
0 1 2 3
0 1.5 3.0 3 3.5
1 2.5 1.5 2 2.5
一次用于列:
In [12]: df.groupby(lambda x: x//2).mean().groupby(lambda y: y//2, axis=1).mean()
Out[12]:
0 1
0 2.25 3.25
1 2.00 2.25
注:只计算一次平均值的解决方案可能更可取。。。一个选项是堆叠、分组、平均和取消堆叠,但这有点繁琐
这似乎比:
事实上,Viktor的解决方案使我的(动力不足的)笔记本电脑崩溃,以获取更大的数据帧:
正如Viktor指出的,这不适用于非整数索引,如果需要,您可以将其存储为临时变量,并在以下情况下反馈:
df_index, df_cols, df.index, df.columns = df.index, df.columns, np.arange(len(df.index)), np.arange(len(df.columns))
res = df.groupby(...
res.index, res.columns = df_index[::2], df_cols[::2]
你想怎么做?每隔两行取一个平均值?我想在子矩阵中对原始矩阵进行切片,然后在每个子矩阵中进行块平均。。e、 g.对于结果矩阵中的元素(1,1),计算原始矩阵中子矩阵(1:2,1:2)的块平均值。我认为2D过滤器内核被称为。我不确定这是我需要的。结果矩阵必须为2x2,其中每个样本是原始矩阵四个元素之间的块平均值。您的解决方案很有趣,但我不明白为什么生成的矩阵是2x4。@Francesco更新了答案。如果您想改进答案,可以将其推广,为行和列添加不同的大小(而不仅仅是为平方矩阵添加bs)。不管怎么说,答案很好:)这似乎不能很好地扩展,例如尝试
df=pd.DataFrame(np.random.randn(100000,100000))
。更小的1000x1000使我的翻译崩溃:(@AndyHayden我在10000x1000矩阵上试过,它在12秒内完成,但是是的,groupby大约比2.86秒快4倍,但它只在列和行标签为整数的情况下有效。没有其他情况会起作用。虽然我没有包括时间,但对于OP的玩具示例来说,这也更快。他说的timeit
关于rolling\u mean
我得到每循环3:4.67毫秒的最佳值
,对于groupby
我得到每循环3:940µs的最佳值
。所以它大约慢了5倍,而不是800倍。@ViktorKerkez我刚刚把你的整个块作为一个函数复制了。这些是我得到的数字,对我来说它崩溃了“大”DataFrames.怪异…我在帖子中添加了我的计时信息:-/在Python3中,确保使用floor division/:df.groupby(lambda x:x//2).mean().groupby(lambda y:y//2,axis=1).mean()
In [12]: df.groupby(lambda x: x//2).mean().groupby(lambda y: y//2, axis=1).mean()
Out[12]:
0 1
0 2.25 3.25
1 2.00 2.25
In [21]: df = pd.DataFrame(np.random.randn(100, 100))
In [22]: %timeit df.groupby(lambda x: x//2).mean().groupby(lambda y: y//2, axis=1).mean()
1000 loops, best of 3: 1.64 ms per loop
In [23]: %timeit viktor()
1 loops, best of 3: 822 ms per loop
In [31]: df = pd.DataFrame(np.random.randn(1000, 1000))
In [32]: %timeit df.groupby(lambda x: x//2).mean().groupby(lambda y: y//2, axis=1).mean()
10 loops, best of 3: 42.9 ms per loop
In [33]: %timeit viktor()
# crashes
df_index, df_cols, df.index, df.columns = df.index, df.columns, np.arange(len(df.index)), np.arange(len(df.columns))
res = df.groupby(...
res.index, res.columns = df_index[::2], df_cols[::2]