熊猫:如何在滚动窗口中选择一列

时间:2017-06-21 10:56:58

标签: python python-2.7 pandas

我有一个数据框(列'a','b','c'),我正在做一个滚动窗口。

我希望能够使用apply函数中的一个列(比如'a')过滤滚动窗口,如下所示

df.rolling(len(s),min_periods=0).apply(lambda x: x[[x['a']>10][0] if len(x[[x['a']>10]]) >=0 else np.nan)

上述行的目的是选择滚动窗口中第一行的“a”列的值大于10.如果没有这样的行,则返回nan。

但我无法这样做并收到以下错误

IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

这意味着我不允许通过这种语法访问各个列。 有没有其他办法做这种事情?

2 个答案:

答案 0 :(得分:5)

您的错误源于假设应用内部函数是一个数据帧,它实际上是一个ndarray而不是一个数据帧。

Pandas数据框应用适用于数据框的每个列/系列,因此传递给apply的任何函数都应用沿每个列/系列(如内部lambda)。在窗口化数据帧的情况下,apply将每个窗口中的每个列/系列作为ndarray传递给函数,并且该函数必须每个窗口每个系列只返回长度为1的数组。知道这一点可以节省很多痛苦。

所以在你的情况下你不能使用任何apply,除非你有一个复杂的函数来记住每个窗口的系列a的第一个值。

对于OP的情况,如果窗口的一栏显示a符合条件,请说> 10

  1. 如果窗口第一行中的a符合条件,则与在数据框df[df['a']>10]中搜索相同。

  2. 对于窗口第二行中的a等其他条件为> 10,检查整个数据框的工作方式除了数据框的第一个窗口外。

  3. 以下示例演示了另一种解决方法。

    import numpy as np
    import pandas as pd
    np.random.seed(123)
    df = pd.DataFrame(np.random.randint(0,20,size=(20, 4)), columns=list('abcd'))
    

    df看起来像

        a   b   b   d
    0   13  2   2   6
    1   17  19  10  1
    2   0   17  15  9
    3   0   14  0   15
    4   19  14  4   0
    5   16  4   17  3
    6   2   7   2   15
    7   16  7   9   3
    8   6   1   2   1
    9   12  8   3   10
    10  5   0   11  2
    11  10  13  18  4
    12  15  11  12  6
    13  13  19  16  6
    14  14  7   11  7
    15  1   11  5   18
    16  17  12  18  17
    17  1   19  12  9
    18  16  17  3   3
    19  11  7   9   2
    

    现在如果在滚动窗口中的第二行符合OP问题中的条件a > 10,则选择一个窗口。

    roll_window=5
    search_index=1
    
    df_roll = df['a'].rolling(roll_window)
    df_y = df_roll.apply(lambda x:x[1] if x[1] > 10 else np.nan).dropna()
    

    上面的行返回大于10的窗口第二行中与条件a对应的a的所有值。注意,这些值是基于上面的示例数据框的,但索引是由滚动的方式定义的窗口居中。

    4     17.0
    7     19.0
    8     16.0
    10    16.0
    12    12.0
    15    15.0
    16    13.0
    17    14.0
    19    17.0
    

    获取正确的索引位置和第一个数据框内的整行

    df.loc[df_y.index+searchindex-rollwindow+1]
    

    返回

        a   b   b   d
    1   17  19  10  1
    4   19  14  4   0
    5   16  4   17  3
    7   16  7   9   3
    9   12  8   3   10
    12  15  11  12  6
    13  13  19  16  6
    14  14  7   11  7
    16  17  12  18  17
    

    还可以使用np.array(df)并制作与滚动窗口相对应的滚动切片,并相应地使用切片过滤数组。

答案 1 :(得分:0)

首先,滚动窗口:

win = df['a'].rolling(len(s), min_periods=0)

然后创建条件(布尔数组):

cond = win > 10

最后:

idx = np.where(cond)[0]
return win.iloc[idx[0]] if len(idx) else np.nan