我想以“滚动”方式获取数据帧子集。我尝试了几件事但没有成功,这是我想做的一个例子。让我们考虑数据框。
df
var1 var2
0 43 74
1 44 74
2 45 66
3 46 268
4 47 66
Run Code Online (Sandbox Code Playgroud)
我想使用以下函数创建一个新列,该列执行条件总和:
def func(x):
tmp = (x["var1"] * (x["var2"] == 74)).sum()
return tmp
Run Code Online (Sandbox Code Playgroud)
并像这样称呼它
df["newvar"] = df.rolling(2, min_periods=1).apply(func)
Run Code Online (Sandbox Code Playgroud)
这意味着该函数将基于数据框应用,而不是针对每一行或每一列
它会回来
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
Run Code Online (Sandbox Code Playgroud)
有没有一种pythonic的方法来做到这一点?这只是一个示例,但条件(始终基于子数据框值取决于 2 列以上。
@unutbu在这里对一个非常相似的问题发布了一个很好的答案,但看来他的答案是基于pd.rolling_apply将索引传递给函数的。我不确定如何用当前DataFrame.rolling.apply方法复制它。
看来通过函数传递给参数的变量apply是每列(一次一个)的 numpy 数组,而不是 DataFrame,因此不幸的是您无法访问任何其他列。
但你可以做的是使用一些布尔逻辑根据是否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
Run Code Online (Sandbox Code Playgroud)
临时列基于上面代码的前半部分。
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
Run Code Online (Sandbox Code Playgroud)
了解实际传递给 apply 函数的内容非常重要,而且我不能总是记住传递的内容,因此如果我不确定,我将打印出变量及其类型,以便我清楚我要传递的对象是什么正在处理。请使用原始 DataFrame 查看此示例。
def foo(x):
print(x)
print(type(x))
return x.sum()
df.rolling(2, min_periods=1).apply(foo)
Run Code Online (Sandbox Code Playgroud)
输出
[ 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'>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5272 次 |
| 最近记录: |