使用滚动 pandas 滑动 window 迭代器
Sliding window iterator using rolling in pandas
如果是单行,我可以得到迭代器如下
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
现在我希望每个迭代器将 return 一个子集 X[0:9, :]
、X[5:14, :]
、X[10:19, :]
等。如何通过滚动实现此目的 (pandas.DataFrame.rolling
)?
滚动不是这样的。它"provides rolling transformations"(来自the docs)。
你可以循环使用pandas indexing?
for i in range((X.shape[0] + 9) // 10):
X_subset = X.iloc[i * 10: (i + 1) * 10])
我将试验以下数据框。
设置
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
它可以用 rolling
完成,但效率低下(由于迭代所有 windows)并且需要 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)):
如果是单行,我可以得到迭代器如下
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
现在我希望每个迭代器将 return 一个子集 X[0:9, :]
、X[5:14, :]
、X[10:19, :]
等。如何通过滚动实现此目的 (pandas.DataFrame.rolling
)?
滚动不是这样的。它"provides rolling transformations"(来自the docs)。
你可以循环使用pandas indexing?
for i in range((X.shape[0] + 9) // 10):
X_subset = X.iloc[i * 10: (i + 1) * 10])
我将试验以下数据框。
设置
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
它可以用 rolling
完成,但效率低下(由于迭代所有 windows)并且需要 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)):