【问题标题】:Pandas dataframe rolling consecutive count熊猫数据框滚动连续计数
【发布时间】:2021-03-31 22:52:37
【问题描述】:

假设,我的 Pandas DataFrame 如下所示:

  account   have  
  A         1     
  A         2     
  A         1     
  A         1     
  A         1     
  A         1     
  A         1     
  A         1     
  A         1     
  B         1     
  B         1     
  B         1     
  B         2     
  B         1     
  B         1     
  B         1     
  B         1     
  B         1     
  B         1  

我希望结果如下所示:

  account   want  
  A         NaN   
  A         NaN   
  A         1     
  A         2     
  A         3     
  A         3     
  A         3     
  A         3     
  A         3     
  B         NaN   
  B         NaN   
  B         3     
  B         2     
  B         1     
  B         2     
  B         3     
  B         3     
  B         3     
  B         3  

背后的想法是给定滚动窗口等于3。我想找到等于1 的最长连续计数。例如,在帐户A 中,在给定窗口等于3 的情况下,等于1 的最长连续计数是1(在索引2 处)。在索引3 处,结果返回2,因为给定窗口包含2, 1, 1 的值。

按照上面相同的逻辑,应用到账户B,结果将如图所示。

关于这个过程的任何建议。

非常感谢!

【问题讨论】:

  • 你能解释一下为什么索引 2 的计数是 1 吗?
  • 因为1的最长连续计数值只有1。给定滚动窗口为3,它包含[1,2,1]的值。因此,这里的窗口中没有连续值,它返回可用的最长连续计数,即 1。

标签: python pandas dataframe conditional-statements rolling-computation


【解决方案1】:

一种方法可能是:

import numpy as np


def compute_max_run(window):
    """Based on this answer https://stackoverflow.com/a/43986888/4001592"""
    diffs = np.diff(window, prepend=0, append=0)

    starts, = np.where(diffs == -1)
    ends, = np.where(diffs == 1)

    if len(ends) and len(starts):
        return (starts - ends).max()
    return 0


def compute(s, w=3, val=1):
    return s.eq(val).rolling(w).apply(compute_max_run)


df['want'] = df.groupby('account')['have'].transform(compute)
print(df)

输出

   account  have  want
0        A     1   NaN
1        A     2   NaN
2        A     1   1.0
3        A     1   2.0
4        A     1   3.0
5        A     1   3.0
6        A     1   3.0
7        A     1   3.0
8        A     1   3.0
9        B     1   NaN
10       B     1   NaN
11       B     1   3.0
12       B     2   2.0
13       B     1   1.0
14       B     1   2.0
15       B     1   3.0
16       B     1   3.0
17       B     1   3.0
18       B     1   3.0

【讨论】:

  • 获取错误的零大小数组以减少操作最大值,没有身份
  • @SasiwutChaiyadecha 输入相同?
  • @SasiwutChaiyadecha 更新了答案。
  • 它可以工作,但我正在尝试应用到我的数据集,它有一百万行,它看起来很慢。
【解决方案2】:

用途:

f = lambda x: 1 if x.iat[1] != 1 else (x == 1).sum()
df['new']=df.groupby('account')['have'].rolling(3).apply(f).reset_index(level=0, drop=True)
print (df)
   account  have  new
0        A     1  NaN
1        A     2  NaN
2        A     1  1.0
3        A     1  2.0
4        A     1  3.0
5        A     1  3.0
6        A     1  3.0
7        A     1  3.0
8        A     1  3.0
9        B     1  NaN
10       B     1  NaN
11       B     1  3.0
12       B     2  2.0
13       B     1  1.0
14       B     1  2.0
15       B     1  3.0
16       B     1  3.0
17       B     1  3.0
18       B     1  3.0

【讨论】:

  • 我有一个非常相似的想法,但我发现当一百万行数据应用时它超级慢。
  • @SasiwutChaiyadecha - 是的,我有一个想法,需要一些时间
  • @SasiwutChaiyadecha - 我认为如果使用 million rows of data. 则需要纯 numpy 或 numba 解决方案而不是 .rolling 函数(因为慢)
  • 使用 numpy 或 numba 有什么建议吗?
  • @SasiwutChaiyadecha - 我尝试了一些东西但失败了:(不幸的是。
猜你喜欢
  • 2019-05-09
  • 1970-01-01
  • 2020-10-29
  • 2018-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-05
  • 2014-09-26
相关资源
最近更新 更多