运行 连续相同值的总数

Running total of consecutive identical values

如何在 pandas 系列中得到 运行 个连续的 1?

例如,s = pd.Series([5, 1, 4, 1, 1, 2, 3, 1, 1, 1, 4])。我想获得pd.Series([0, 1, 0, 1, 2, 0, 0, 1, 2, 3, 0]).

(Pandas 0.18.0)

不是最漂亮的方法(也可能不是最佳的),但以下方法可以完成工作(并且比其他循环答案快 4.5 倍):

s = pd.Series([5, 1, 4, 1, 1, 2, 3, 1, 1, 1, 4])

def consecutive_n(s, n=1):
    a = s[s==n].cumsum()[s.index].fillna(0) / n
    b = a[a.diff() > 1]
    c = (b.rank() - b)[s.index].fillna(0).cumsum()
    return (a + c).apply(lambda x: np.where(x<0, 0, x)).astype(int)

>>> consecutive_n(s, n=1)
0     0
1     1
2     0
3     1
4     2
5     0
6     0
7     1
8     2
9     3
10    0
dtype: int64

中间值的一些解释:
a: 1 在整个系列中第 n 次出现。
c:当 1(或 n)之间出现不同的数字时,必须将 a 添加到 "reset" 的出现次数。 return 值:应用 lambda 忽略形成 a + c.

的负数

编辑: 稍微更改了代码,使其适用于任何正整数。示例:

>>> t = pd.Series([1, 2, 3, 1, 4, 2, 2, 3, 2, 2, 2, 1])
>>> consecutive_n(t, 2)
0     0
1     1
2     0
3     0
4     0
5     1
6     2
7     0
8     1
9     2
10    3
11    0
dtype: int64

你可以试试groupby with cumcount comparing s1 != 1 with cumsum:

print s1.groupby((s1 != 1).cumsum()).cumcount()
0     0
1     1
2     0
3     1
4     2
5     0
6     0
7     1
8     2
9     3
10    0
dtype: int64

更好的解释:

df = pd.DataFrame(s1, columns=['orig'])
df['not1'] = s1 != 1
df['cumsum'] = (s1 != 1).cumsum()
df['cumcount'] = s1.groupby((s1 != 1).cumsum()).cumcount()
#s1.groupby((s1 != 1).cumsum()).cumcount() is same as:
df['cumcount1'] = df.groupby('cumsum')['orig'].cumcount()
print df
    orig   not1  cumsum  cumcount  cumcount1
0      5   True       1         0          0
1      1  False       1         1          1
2      3   True       2         0          0
3      4   True       3         0          0
4      1  False       3         1          1
5      1  False       3         2          2
6      2   True       4         0          0
7      3   True       5         0          0
8      1  False       5         1          1
9      1  False       5         2          2
10     1  False       5         3          3
11     4   True       6         0          0

或者:

print (s1 == 1) * (s1.groupby((s1 != s1.shift()).cumsum()).cumcount() + 1)
0     0
1     1
2     0
3     1
4     2
5     0
6     0
7     1
8     2
9     3
10    0
dtype: int64

解释:

df = pd.DataFrame(s1, columns=['orig'])
df['compare_shift'] = s1 != s1.shift()
df['cumsum'] = (s1 != s1.shift()).cumsum()
df['cumcount'] = s1.groupby((s1 != s1.shift()).cumsum()).cumcount() + 1
df['cumcount1'] = df.groupby('cumsum')['orig'].cumcount() + 1
df['is1'] = (s1 == 1)
#True in converted to 1, False to 0
df['fin'] = (s1 == 1) * (s1.groupby((s1 != s1.shift()).cumsum()).cumcount() + 1)
print df
    orig compare_shift  cumsum  cumcount  cumcount1    is1  fin
0      5          True       1         1          1  False    0
1      1          True       2         1          1   True    1
2      3          True       3         1          1  False    0
3      4          True       4         1          1  False    0
4      1          True       5         1          1   True    1
5      1         False       5         2          2   True    2
6      2          True       6         1          1  False    0
7      3          True       7         1          1  False    0
8      1          True       8         1          1   True    1
9      1         False       8         2          2   True    2
10     1         False       8         3          3   True    3
11     4          True       9         1          1  False    0