【问题标题】:Pandas DataFrame.rolling window with MultiIndex带有 MultiIndex 的 Pandas DataFrame.rolling 窗口
【发布时间】:2018-06-03 10:05:56
【问题描述】:

如何应用 DataFrame.rolling 函数并将值分配回原始 DataFrame?

例如,

i = pd.MultiIndex.from_product([['A','B','C'], np.arange(1, 11, 1)], names=['Name','Num'])
df = pd.DataFrame(np.random.randn(30), i, columns=['Vals'])
window = df.groupby(['Name']).rolling(3, min_periods=3)
df['Window'] = window['Vals'].apply(lambda x: x[1] + x[2])

在这种情况下,我希望使用每个 Name 值重置滚动 lambda,因此对于每个 Name 的前 3 行,Window 将是 NaN。但是,最后分配给 DataFrame 的新列会产生一列 完全 NaN

示例窗口 lambda 基本上可以正常工作,但我注意到它将分组值添加到 MultiIndex。请注意以下有两个级别称为Name

window['Vals'].apply(lambda x: x[1] + x[2]) # Returns:
Name  Name  Num
A     A     1           NaN
            2           NaN
            3     -2.408704
            4     -3.184169
            5      0.207093
            6      1.649017
            7      0.789064
            8      0.706335
            9     -0.487192
            10    -1.625869
B     B     1           NaN
            2           NaN
            3      0.023201
            4     -0.044582
            5      0.409526

我是否错误地使用了这些方法,或者没有做一些必要的事情来让window.apply() 与 DataFrame 对齐?

【问题讨论】:

  • 你想用滚动功能做什么?
  • @cᴏʟᴅsᴘᴇᴇᴅ 前面Vals的线性组合。
  • 我了解您的问题。我会试试看能不能找到解决办法。
  • @cᴏʟᴅsᴘᴇᴇᴅ - 很酷,谢谢。请注意,我们可以在df.groupby().rolling()...apply() 的结果上调用index = index.droplevel()。但由于我不明白是否/何时/为什么添加额外级别,我担心将来会停止工作。
  • 我没有解释为什么要处理额外的级别,但是您总是可以从结果中取出 .values 并将其分配回去,没有任何问题。 df['Window'] = window['Vals'].apply(lambda x: x[1] + x[2]).values.

标签: python pandas dataframe multi-index pandas-groupby


【解决方案1】:

这是一个想法。交换索引级别。然后解压。计算滚动窗口。然后堆叠。

交换索引级别:

df.set_index(df.index.swaplevel(),inplace=True)

取消堆叠

df=df.unstack(level=1)

计算滚动窗口总和并重新堆叠。

df.rolling(3,min_periods=3).sum().stack()

然后换回索引

一口气读成:

# Your setup
import pandas as pd
i = pd.MultiIndex.from_product([['A','B','C'], np.arange(1, 11, 1)], names=['Name','Num'])
df = pd.DataFrame(np.random.randn(30), i, columns=['Vals'])

# Idea
def swap_index(df):
    return(df.set_index(df.index.swaplevel()))
df2=swap_index(swap_index(df).unstack(level=1).rolling(3,min_periods=3).sum().stack())

输出是

In [1129]: df2
Out[1129]:
              Vals
Name Num
A    3    0.713198
B    3    1.040715
C    3    0.607588
A    4    0.992321
B    4    0.318793
C    4    0.716161
A    5    1.422214
B    5   -0.870407
C    5    0.440496
A    6   -0.496093
B    6    0.947817
C    6    0.163391
A    7    0.587050
B    7    1.594572
C    7    0.022100
A    8   -0.283013
B    8    4.316982
C    8   -0.312434
A    9    1.695324
B    9    1.100592
C    9   -0.002113
A    10   0.651203
B    10   1.077666
C    10  -0.268794

如果您想要 1 和 2 的 NaN,则需要从原始索引创建一个空数据框并与之合并。这仍然有点痛苦,但也许这已经对你有用了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 2021-04-18
    • 2021-02-06
    • 1970-01-01
    • 2017-10-12
    • 2016-02-04
    • 1970-01-01
    相关资源
    最近更新 更多