【发布时间】:2018-07-27 02:57:34
【问题描述】:
(与this answer相关)
给定一个df,我期待得到df.expanding() 的结果,并使用.apply() 对此执行一些多变量操作(同时涉及df 的几列在一个扩展的行窗口上的操作)。事实证明这是不可能的。
因此,就像上面链接的答案一样,我需要使用numpy.as_strides 或df。除了与上面链接的问题相比,使用 strides 来获得我的df 的扩展视图,而不是滚动视图(扩展窗口具有固定的左侧,右侧逐渐向右移动)。
考虑一下df:
import numpy
import pandas
df = pandas.DataFrame(numpy.random.normal(0, 1, [100, 2]), columns=['size_A', 'size_B']).cumsum(axis=0)
考虑使用此代码提取 W 行的滚动窗口 df(这来自上面的答案):
def get_sliding_window(df, W):
a = df.values
s0,s1 = a.strides
m,n = a.shape
return numpy.lib.stride_tricks\
.as_strided(a,shape=(m-W+1,W,n),strides=(s0,s0,s1))
roll_window = get_sliding_window(df, W = 3)
roll_window[2]
现在我想修改get_sliding_window 让它返回
df 的扩展窗口(而不是滚动窗口):
def get_expanding_window(df):
a = df.values
s0,s1 = a.strides
m,n = a.shape
out = numpy.lib.stride_tricks\
.as_strided(a, shape=(m,m,n),strides=(s0,s0,s1))
return out
expg_window = get_expanding_window(df)
expg_window[2]
但我没有正确使用as_strided 的参数:我似乎无法获得正确的矩阵——这将是这样的:
[df.iloc[0:1].values ,df.iloc[0:2].values, df.iloc[0:3].values,...]
编辑:
@ThomasKühn 在评论中建议使用列表理解。 这将解决问题,但太慢了。费用是多少?
一个向量值函数,我们可以比较成本
使用.expand() 进行列表理解。不小:
numpy.random.seed(123)
df = pandas.DataFrame((numpy.random.normal(0, 1, 10000)), columns=['Value'])
%timeit method_1 = numpy.array([df.Value.iloc[range(j + 1)].sum() for j in range(df.shape[0])])
给予:
6.37 s ± 219 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
对比.expanding():
%timeit method_2 = df.expanding(0).apply(lambda x: x.sum())
给出:
35.5 ms ± 356 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
最后,关于我要解决的问题的更多细节 在 cmets 中向this 提问。
【问题讨论】:
-
你的意思是想让窗口的左边固定,右边移动到右边?
-
@ThomasKühn:是的(编辑问题以使其更清楚)。谢谢!
-
我认为
strides无法实现您想要做的事情,因为它们似乎假定长度固定。我想你想要的是slices。对我来说,这看起来有点像xy problem。您能否详细说明您要完成的工作? -
这个怎么样:
indices = [i for j in range(1,5) for i in range(j)]然后df.iloc[indices]。这就是你想要的吗? -
...但是您需要保留这些切片,还是只是对它们进行一些计算?仅访问数组的切片(例如
a[3:5])只会创建数组的view,因此不会复制任何数据。另见documentation:“所有由基本切片生成的数组始终是原始数组的视图。”