【问题标题】:Pandas: How to select a column in rolling window熊猫:如何在滚动窗口中选择一列
【发布时间】:2017-06-21 10:56:57
【问题描述】:

我有一个数据框(包含“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

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

【问题讨论】:

  • 你检查过x[[x['a']>10][0]是什么吗?
  • @AndrewL 显然我根本不允许访问“a”列。错误是说索引只能是整数、切片 (:)、省略号 (...)、numpy.newaxis (None) 和整数或布尔数组
  • 查看示例数据会很有帮助
  • 顺便说一句,您根本没有选择“a”列-您将其应用于整个数据框。您需要更改为:df['a'].rolling(len(s),min_periods=0).apply()

标签: python python-2.7 pandas


【解决方案1】:

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

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

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

对于 OP 的情况,如果窗口的一列说 a 满足条件,说 > 10

  1. 对于窗口第一行中的a 满足条件的情况,与在数据框df[df['a']>10] 中搜索相同。

  2. 对于其他条件,例如窗口第二行中的a> 10,检查整个数据框,除了数据框的第一个窗口。

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

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

如果 a 的滚动窗口内的第二行满足条件 a > 10 就像 OP 的问题一样,现在选择一个窗口。

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),制作一个与滚动窗口对应的滚动切片,并使用相应的切片过滤数组。

【讨论】:

  • 关于滚动窗口的第一行,这只是我给出的一个例子。
  • @ishan3243 其他行也应该给出类似的答案,除了第一个窗口。不过,我确实为您制定了另一个通用解决方案。
【解决方案2】:

首先,制作滚动窗口:

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

【讨论】:

  • 我不确定我是否理解代码中发生的事情。 cond 变量对我来说没有意义。你能解释一下吗?
  • @John Zwinck 你的条件是 bool 而不是 bool 数组,所以似乎不起作用
猜你喜欢
  • 2017-03-30
  • 2020-04-21
  • 2021-03-30
  • 2021-04-06
  • 1970-01-01
  • 1970-01-01
  • 2020-09-21
  • 2018-07-10
  • 1970-01-01
相关资源
最近更新 更多