使用 Pandas 中的滚动窗口迭代器实现滑动窗口。

9
如果是单行的话,我可以按照以下方式获取迭代器。
import pandas as pd
import numpy as np

a = np.zeros((100,40))
X = pd.DataFrame(a)

for index, row in X.iterrows():
    print index
    print row

现在我希望每个迭代器都返回一个子集 X[0:9, :], X[5:14, :], X[10:19, :] 等等。我该如何使用 rolling (pandas.DataFrame.rolling) 实现这一点?


1
什么是X?什么是滚动? - Mad Physicist
3
好的。X[0:9]是什么意思? 答:X[0:9]表示X中从索引0开始到索引8(不包括索引9)的子字符串。 - Mad Physicist
2
据我所知,iterrows 比使用索引切片始终要慢。你的数据集有多大? - Merlin
2
你可能需要修剪这500列。尽量只使用必要的内容,而不是全部。 - Merlin
2
我更新了我的解决方案,返回可迭代对象,这样你就不需要记得堆叠。 - piRSquared
显示剩余4条评论
3个回答

7
我将尝试使用以下数据框进行实验。

设置

import pandas as pd
import numpy as np
from string import uppercase

def generic_portfolio_df(start, end, freq, num_port, num_sec, seed=314):
    np.random.seed(seed)
    portfolios = pd.Index(['Portfolio {}'.format(i) for i in uppercase[:num_port]],
                          name='Portfolio')
    securities = ['s{:02d}'.format(i) for i in range(num_sec)]
    dates = pd.date_range(start, end, freq=freq)
    return pd.DataFrame(np.random.rand(len(dates) * num_sec, num_port),
                        index=pd.MultiIndex.from_product([dates, securities],
                                                         names=['Date', 'Id']),
                        columns=portfolios
                       ).groupby(level=0).apply(lambda x: x / x.sum())    


df = generic_portfolio_df('2014-12-31', '2015-05-30', 'BM', 3, 5)

df.head(10)

enter image description here

我现在将介绍一个函数来滚动多行并将它们连接成一个单独的数据框,其中我将添加一个顶级到列索引,指示滚动中的位置。

解决方案步骤1

def rolled(df, n):
    k = range(df.columns.nlevels)
    _k = [i - len(k) for i in k]
    myroll = pd.concat([df.shift(i).stack(level=k) for i in range(n)],
                       axis=1, keys=range(n)).unstack(level=_k)
    return [(i, row.unstack(0)) for i, row in myroll.iterrows()]
< p > 虽然它藏在函数中,但 < code > myroll 看起来像这样

enter image description here

现在我们可以像使用迭代器一样使用它。

解决方案步骤二

for i, roll in rolled(df.head(5), 3):
    print roll
    print

                    0   1   2
Portfolio                    
Portfolio A  0.326164 NaN NaN
Portfolio B  0.201597 NaN NaN
Portfolio C  0.085340 NaN NaN

                    0         1   2
Portfolio                          
Portfolio A  0.278614  0.326164 NaN
Portfolio B  0.314448  0.201597 NaN
Portfolio C  0.266392  0.085340 NaN

                    0         1         2
Portfolio                                
Portfolio A  0.258958  0.278614  0.326164
Portfolio B  0.089224  0.314448  0.201597
Portfolio C  0.293570  0.266392  0.085340

                    0         1         2
Portfolio                                
Portfolio A  0.092760  0.258958  0.278614
Portfolio B  0.262511  0.089224  0.314448
Portfolio C  0.084208  0.293570  0.266392

                    0         1         2
Portfolio                                
Portfolio A  0.043503  0.092760  0.258958
Portfolio B  0.132221  0.262511  0.089224
Portfolio C  0.270490  0.084208  0.293570

你有看过 np.strides 吗?我正在处理的某个东西可能会用到上面提到的内容。 - Merlin

1

那不是滚动的工作方式。它“提供滚动转换”(来自文档)。

你可以循环并使用pandas索引吗?

for i in range((X.shape[0] + 9) // 10):
    X_subset = X.iloc[i * 10: (i + 1) * 10])

2
我该如何获取一个类似于iterrows()的迭代器呢? - Dzung Nguyen

1

可以使用rolling实现,但效率较低(因为需要迭代所有窗口),并且需要Pandas 1.1版本:

for index, row in enumerate(list(X.rolling(10))[::5]):

更快的方式(C语言迭代)

from itertools import islice
for index, row in enumerate(islice(X.rolling(10), None, None, 5)):

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接