如何获取滚动熊猫数据帧子集



我想以"滚动"的方式获取数据帧子集。 我尝试了几件事都没有成功,这里有我想做的一个例子。让我们考虑数据帧。

df
var1      var2
0    43         74
1    44         74
2    45         66
3    46        268
4    47         66

我想使用以下函数创建一个新列,该函数执行条件求和:

def func(x):
tmp = (x["var1"] * (x["var2"] == 74)).sum()
return tmp

并这样称呼它

df["newvar"] = df.rolling(2, min_periods=1).apply(func)

这意味着该函数将基于数据帧应用,而不是应用于每一行或每一列

它会返回

var1      var2      newvar
0    43         74         43          # 43
1    44         74         87          # 43 * 1 + 44 * 1
2    45         66         44          # 44 * 1 + 45 * 0
3    46        268         0           # 45 * 0 + 46 * 0
4    47         66         0           # 46 * 0 + 47 * 0

有没有一种pythonic方法可以做到这一点? 这只是一个例子,但条件(始终基于子数据帧值取决于 2 列以上。

更新的评论

@unutbu在这里发布了一个非常相似的问题的很好的答案,但似乎他的答案是基于将索引传递给函数pd.rolling_apply。我不确定如何使用当前的DataFrame.rolling.apply方法复制它。

原始答案

似乎通过apply函数传递给参数的变量是每列的 numpy 数组(一次一个),而不是数据帧,因此不幸的是,您无法访问任何其他列。

但是你可以做的是使用一些布尔逻辑,根据var2是否为 74 临时创建一个新列,然后使用滚动方法。

df['new_var'] = df.var2.eq(74).mul(df.var1).rolling(2, min_periods=1).sum()
var1  var2  new_var
0    43    74     43.0
1    44    74     87.0
2    45    66     44.0
3    46   268      0.0
4    47    66      0.0

临时列基于上述代码的前半部分。

df.var2.eq(74).mul(df.var1)
# or equivalently with operators
# (df['var2'] == 74) * df['var1']
0    43
1    44
2     0
3     0
4     0

查找要应用的传递变量的类型

知道实际传递给 apply 函数的内容非常重要,我不能总是记住正在传递的内容,所以如果我不确定,我会打印出变量及其类型,以便我清楚我正在处理什么对象。请参阅此示例与原始数据帧。

def foo(x):
print(x)
print(type(x))
return x.sum()
df.rolling(2, min_periods=1).apply(foo)

输出

[ 43.]
<class 'numpy.ndarray'>
[ 43.  44.]
<class 'numpy.ndarray'>
[ 44.  45.]
<class 'numpy.ndarray'>
[ 45.  46.]
<class 'numpy.ndarray'>
[ 46.  47.]
<class 'numpy.ndarray'>
[ 74.]
<class 'numpy.ndarray'>
[ 74.  74.]
<class 'numpy.ndarray'>
[ 74.  66.]
<class 'numpy.ndarray'>
[  66.  268.]
<class 'numpy.ndarray'>
[ 268.   66.]
<class 'numpy.ndarray'>

诀窍是定义一个可以访问整个数据帧的函数。然后,您在任何列上执行滚动,并在传入该函数apply()调用。该函数将有权访问窗口数据,该数据是数据帧列的子集。从该子集中,您可以提取应查看的索引。(这假设您的指数正在严格增加。因此,通常的整数索引以及大多数时间序列都可以使用。然后,可以使用索引访问包含所有列的整个数据帧。

def dataframe_roll(df):
def my_fn(window_series):
window_df = df[(df.index >= window_series.index[0]) & (df.index <= window_series.index[-1])]
return window_df["col1"] + window_df["col2"]
return my_fn
df["result"] = df["any_col"].rolling(24).apply(dataframe_roll(df), raw=False)

下面介绍了如何以滚动方式获取数据帧子集:

for df_subset in df.rolling(2):
print(type(df_subset), 'n', df_subset)

最新更新