【问题标题】:How to get rolling pandas dataframe subsets如何获得滚动的熊猫数据框子集
【发布时间】:2017-01-17 15:39:47
【问题描述】:

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

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 列以上。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    更新评论

    @unutbu 向a very similar question here 发布了一个很好的答案,但似乎他的答案是基于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
    

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

    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的变量的类型

    知道实际传递给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'>
    

    【讨论】:

      【解决方案2】:

      诀窍是定义一个可以访问整个数据框的函数。然后你在任何列上滚动并调用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)
      

      【讨论】:

        【解决方案3】:

        以下是您以滚动方式获取数据帧子集的方法:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-03-28
          • 2021-06-02
          • 1970-01-01
          • 2021-12-04
          • 2013-04-14
          • 1970-01-01
          • 1970-01-01
          • 2015-05-10
          相关资源
          最近更新 更多