我想在"滚动"中获取数据帧子集。方式。 我尝试了几件事没有成功,这是我想做的一个例子。我们来考虑数据帧。
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列。
答案 0 :(得分:3)
@unutbu给a very similar question here发了一个很好的答案,但似乎他的答案是基于pd.rolling_apply
,它将索引传递给函数。我不确定如何使用当前的DataFrame.rolling.apply
方法复制它。
看来通过apply
函数传递给参数的变量是每列的一个numpy数组(一次一个),而不是DataFrame,所以不幸的是你无法访问任何其他列。 / p>
但你可以做的是使用一些布尔逻辑根据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函数的内容非常重要,我不能永远记住传递的内容,所以如果我不确定我会打印出变量及其类型,以便我很清楚我正在处理什么对象。请使用原始DataFrame查看此示例。
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'>
答案 1 :(得分:1)
诀窍是定义一个可以访问整个数据框的函数。然后,在任何列上滚动,并调用传递该函数的apply()
。该函数将有权访问窗口数据,该数据是dataframe列的子集。从该子集中,您可以提取应该查看的索引。 (这假设您的索引严格增加。因此,通常的整数索引以及大多数时间序列都可以使用。)您可以使用索引来访问所有列的整个数据框。
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)