【问题标题】:Sliding window iterator using rolling in pandas使用 pandas 滚动的滑动窗口迭代器
【发布时间】:2016-11-25 08:00:54
【问题描述】:

如果是单行,我可以得到如下迭代器

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, :] 等。如何通过滚动 (pandas.DataFrame.rolling) 实现这一目标?

【问题讨论】:

  • 什么是 X?什么是滚动?
  • 好的。 X[0:9] 是什么意思?
  • 是的,据我所知 iterrows 总是比使用索引切片慢。你的数据集有多大。
  • 您可能需要修剪 500 列。只使用你需要的东西而不是所有东西。
  • 我更新了我的解决方案以返回可迭代对象,这样您就不需要记住堆栈了。

标签: python pandas numpy dataframe pandas-groupby


【解决方案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)):

【讨论】:

    【解决方案2】:

    我将尝试以下数据框。

    设置

    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)
    

    我现在将介绍一个函数,用于滚动多个行并连接到单个数据帧中,在该数据帧中,我将向列索引添加一个顶层,以指示滚动中的位置。

    解决方案步骤 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()]
    

    虽然它隐藏在函数中,myroll 看起来像这样

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

    解决方案步骤 2

    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 吗?可能会在我正在做的事情上使用上述内容。
    【解决方案3】:

    滚动不是这样工作的。它“提供滚动转换”(来自the docs)。

    你可以循环使用pandas indexing?

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

    【讨论】:

    • 如何获取迭代器,类似于 iterrows()?
    猜你喜欢
    • 2011-10-12
    • 1970-01-01
    • 2021-06-22
    • 2012-10-12
    • 2021-05-19
    • 2010-10-09
    • 2013-01-15
    • 2014-12-09
    • 1970-01-01
    相关资源
    最近更新 更多