【问题标题】:Python - Pandas, Rolling Mean, and difficult Groupby common ID with a few select parametersPython - 带有几个选择参数的 Pandas、Rolling Mean 和困难的 Groupby 通用 ID
【发布时间】:2015-07-29 21:04:49
【问题描述】:

您好,我无法从 python 中的滚动均值和 groupby 函数创建所需的输出。下面是我的数据框的快照....

    var_x = range(0, 12)
    var_y = range(20, 44, 2)
    var_z = range(0, 60, 5) 
    ID = ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'c', 'c', 'c']
    df = DataFrame(zip(ID, var_x, var_y, var_z), columns = ['id', 'var_x', 'var_y', 'var_z'])

    df
    id   var_x   var_y   var_z
    a   0  20   0
    a   1  22   5
    a   2  24  10
    a   3  26  15
    b   4  28  20
    b   5  30  25
    b   6  32  30
    b   7  34  35
    b   8  36  40
    c   9  38  45
    c  10  40  50
    c  11  42  55

利用这些数据,我试图完成 3 件事: - 首先,我想使用 groupby 为“id”字段计算滚动平均值。我可以为单个列执行此操作,但不能针对每个数字字段(var_y,var_z),使用以下代码。

    df.groupby('id')['var_x'].apply(pd.rolling_mean, 3) 
  • 其次,我希望前 3 个 ID 的平均值填充当前 ID,而当前 ID 的值不包含在当前滚动平均迭代中(可能有移位?)。例如,一个看起来像这样的输出......

    0    NaN    NaN    NaN
    1    NaN    NaN    NaN
    2    NaN    NaN    NaN
    3      1    22     5
    4    NaN    NaN    NaN
    5    NaN    NaN    NaN
    6    NaN    NaN    NaN 
    7      5    30     25
    8      6    32     30
    9     NaN   NaN    NaN
    10    NaN   NaN    NaN
    11    NaN   NaN    NaN
    

注意第 4 个“a”是前 3 个 a 的平均值。第 4 个和第 5 个 b 也是如此(取前 3 个平均值的值,同时排除其自身的值)。

  • 第三,对于以“NaN”结尾的 ID(每个新 ID 的前三个),我想迭代地将窗口从 3 减小到 1(如果可能),以便唯一具有 NaN 的值是每个 ID 的第一个实例。所需的输出将是...

    0    NaN    NaN    NaN
    1      0    20     0
    2    0.5    21     2.5
    3      1    22     5
    4    NaN    NaN    NaN
    5      4    28     20
    6    4.5    29     22.5 
    7      5    30     25
    8      6    32     30
    9     NaN   NaN    NaN
    10    9     38     45
    11    9.5   39     47.5       
    

注意第 3 个 a 是前 2 个 a 的平均值。第二个 a 是第一个等的值...

任何帮助将不胜感激。

【问题讨论】:

  • 我建议您将问题分成不同的帖子。
  • 这是一个公平的观点,但我认为在这种情况下做 3 可能还可以,只有第三个需要很多努力。
  • 谢谢,问题的第三部分对我个人来说是一个令人费解的问题......但仍然非常感谢您对第一部分的任何帮助。

标签: python pandas


【解决方案1】:

让我首先通过将“id”作为索引来对示例数据进行轻微更改。这主要是通过保存一列来简化数据,但也有解决问题1的副作用。

df = pd.DataFrame({'var_x':range(12), 'var_y':range(20,44,2), 'var_z':range(0,60,5)}, 
                   index=list('aaaabbbbbccc'))

   var_x  var_y  var_z
a      0     20      0
a      1     22      5
a      2     24     10
a      3     26     15
b      4     28     20
b      5     30     25
b      6     32     30
b      7     34     35
b      8     36     40
c      9     38     45
c     10     40     50
c     11     42     55

由于数据更改,您还将 groupby 语法更改为 level=0。老实说,我不太确定为什么这可以解决您的第一个问题,但我确信有一种方法可以在不将索引设置为“id”变量的情况下做到这一点。总之……

df2 = df.groupby(level=0).apply(pd.rolling_mean, 3)

   var_x  var_y  var_z
a    NaN    NaN    NaN
a    NaN    NaN    NaN
a      1     22      5
a      2     24     10
b    NaN    NaN    NaN
b    NaN    NaN    NaN
b      5     30     25
b      6     32     30
b      7     34     35
c    NaN    NaN    NaN
c    NaN    NaN    NaN
c     10     40     50

第二部分很简单,只是另一个 groupby,但这次是 shift。

df_win3 = df2.groupby(level=0).shift()

   var_x  var_y  var_z
a    NaN    NaN    NaN
a    NaN    NaN    NaN
a    NaN    NaN    NaN
a      1     22      5
b    NaN    NaN    NaN
b    NaN    NaN    NaN
b    NaN    NaN    NaN
b      5     30     25
b      6     32     30
c    NaN    NaN    NaN
c    NaN    NaN    NaN
c    NaN    NaN    NaN

第三部分只是用不同的窗口重复前2步。

df_win2 = df.groupby(level=0).apply(pd.rolling_mean, 2).groupby(level=0).shift()
df_win1 = df.groupby(level=0).apply(pd.rolling_mean, 1).groupby(level=0).shift()

然后使用combine_first 将值从最左边的数据框(如果可用)中保留的位置合并。

df_win3.combine_first(df_win2).combine_first(df_win1)

   var_x  var_y  var_z
a    NaN    NaN    NaN
a    0.0     20    0.0
a    0.5     21    2.5
a    1.0     22    5.0
b    NaN    NaN    NaN
b    4.0     28   20.0
b    4.5     29   22.5
b    5.0     30   25.0
b    6.0     32   30.0
c    NaN    NaN    NaN
c    9.0     38   45.0
c    9.5     39   47.5

【讨论】:

  • 谢谢约翰,这就是我在输出中寻找的内容,我能够使其与原始数据集一起工作,并按 id 分组,并传递向量列表来执行 rolling_mean on.... All = ['var_x', 'var_y', 'var_z'] 然后... df.groupby(df['id'])[All].apply(pd.rolling_mean, 3).groupby( df['id']).shift()
猜你喜欢
  • 2021-05-18
  • 2020-03-19
  • 1970-01-01
  • 2016-10-17
  • 2018-08-04
  • 1970-01-01
  • 2020-09-25
  • 2017-09-14
  • 2016-07-16
相关资源
最近更新 更多