【问题标题】:How to count consecutive repetitions in a pandas series如何计算熊猫系列中的连续重复次数
【发布时间】:2019-12-07 12:09:45
【问题描述】:

考虑以下系列,ser

date        id 
2000        NaN
2001        NaN 
2001        1
2002        1
2000        2
2001        2
2002        2
2001        NaN
2010        NaN
2000        1
2001        1
2002        1
2010        NaN

如何计算每个连续数字的值并返回?谢谢。

Count
NaN     2 
1       2 
2       3
NaN     2
1       3
NaN     1

【问题讨论】:

  • this 是您要找的吗?
  • @Guy 它似乎不起作用。也许是因为nan
  • 这基本上是运行长度编码。当你用你最喜欢的搜索引擎寻找它时,你可能会找到一些实现;)
  • @sophros 棘手的部分是那些答案/问题无法处理的 NaN。

标签: python pandas


【解决方案1】:

cumsum 技巧在这里很有用,不过它对 NaN 有点棘手,所以我认为您需要分别处理这些:

In [11]: df.id.isnull() & df.id.shift(-1).isnull()
Out[11]:
0      True
1     False
2     False
3     False
4     False
5     False
6     False
7      True
8     False
9     False
10    False
11    False
12     True
Name: id, dtype: bool

In [12]: df.id.eq(df.id.shift(-1))
Out[12]:
0     False
1     False
2      True
3     False
4      True
5      True
6     False
7     False
8     False
9      True
10     True
11    False
12    False
Name: id, dtype: bool

In [13]: (df.id.isnull() & df.id.shift(-1).isnull()) | (df.id.eq(df.id.shift(-1)))
Out[13]:
0      True
1     False
2      True
3     False
4      True
5      True
6     False
7      True
8     False
9      True
10     True
11    False
12     True
Name: id, dtype: bool

In [14]: ((df.id.isnull() & df.id.shift(-1).isnull()) | (df.id.eq(df.id.shift(-1)))).cumsum()
Out[14]:
0     1
1     1
2     2
3     2
4     3
5     4
6     4
7     5
8     5
9     6
10    7
11    7
12    8
Name: id, dtype: int64

现在你可以在你的 groupby 中使用这个标签了:

In [15]: g = df.groupby(((df.id.isnull() & df.id.shift(-1).isnull()) | (df.id.eq(df.id.shift(-1)))).cumsum())

In [16]: pd.DataFrame({"count": g.id.size(), "id": g.id.nth(0)})
Out[16]:
    count   id
id
1       2  NaN
2       2  1.0
3       1  2.0
4       2  2.0
5       2  NaN
6       1  1.0
7       2  1.0
8       1  NaN

【讨论】:

  • 输出与问题的输出不匹配。
  • @Oli 是的,但非常接近,特别是 OPs 输出有点糟糕,因为它在索引中有重复项(和 NaN)。使用reset_index() 将是相同的......
  • 同意安迪的观点:唯一索引有clear performance benefits。除此之外,它作为“索引”更有意义。
【解决方案2】:

这是使用fillna 处理NaN 值的另一种方法:

s = df.id.fillna('nan')
mask = s.ne(s.shift())

ids = s[mask].to_numpy()
counts = s.groupby(mask.cumsum()).cumcount().add(1).groupby(mask.cumsum()).max().to_numpy()

# Convert 'nan' string back to `NaN`
ids[ids == 'nan'] = np.nan
ser_out = pd.Series(counts, index=ids, name='counts')

[出]

nan    2
1.0    2
2.0    3
nan    2
1.0    3
nan    1
Name: counts, dtype: int64

【讨论】:

  • 漂亮。谢谢
  • 我们能否将字符串nan 替换为最后的双精度nan
  • 如果将输出分配给一个新变量ser_out,可能是ser_out.index = ser_out.index.where(ser_out.index != 'nan') 之类的......?或者更好的是,ids[ids == 'nan'] = np.nanSeries 构造函数之前
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 2019-03-04
  • 2023-03-10
相关资源
最近更新 更多