我有一个看起来如下的系列:
col
0 B
1 B
2 A
3 A
4 A
5 B
Run Code Online (Sandbox Code Playgroud)
这是一个时间序列,因此索引按时间排序.
对于每一行,我想计算该值连续出现的次数,即:
输出:
col count
0 B 1
1 B 2
2 A 1 # Value does not match previous row => reset counter to 1
3 A 2
4 A 3
5 B 1 # Value does not match previous row => reset counter to 1
Run Code Online (Sandbox Code Playgroud)
我找到了2个相关问题,但我无法弄清楚如何将这些信息"写"为DataFrame中的新列,每行(如上所述).使用rolling_apply效果不佳.
有关:
P.T*_*ann 39
我觉得这是对@chrisb和@CodeShaman的解决方案相结合的好办法(正如有人指出CodeShamans解决方案总计算,而不是连续值).
df['count'] = df.groupby((df['col'] != df['col'].shift(1)).cumsum()).cumcount()+1
col count
0 B 1
1 B 2
2 A 1
3 A 2
4 A 3
5 B 1
Run Code Online (Sandbox Code Playgroud)
Cod*_*man 20
一内胆:
df['count'] = df.groupby('col').cumcount()
Run Code Online (Sandbox Code Playgroud)
要么
df['count'] = df.groupby('col').cumcount() + 1
Run Code Online (Sandbox Code Playgroud)
如果你想让计数从1开始.
chr*_*isb 14
根据您链接的第二个答案,假设s是您的系列.
df = pd.DataFrame(s)
df['block'] = (df['col'] != df['col'].shift(1)).astype(int).cumsum()
df['count'] = df.groupby('block').transform(lambda x: range(1, len(x) + 1))
In [88]: df
Out[88]:
col block count
0 B 1 1
1 B 1 2
2 A 2 1
3 A 2 2
4 A 2 3
5 B 3 1
Run Code Online (Sandbox Code Playgroud)
我喜欢@chrisb的答案,但想分享我自己的解决方案,因为有些人可能会发现它更易读,更容易使用类似的问题....
1)创建一个使用静态变量的函数
def rolling_count(val):
if val == rolling_count.previous:
rolling_count.count +=1
else:
rolling_count.previous = val
rolling_count.count = 1
return rolling_count.count
rolling_count.count = 0 #static variable
rolling_count.previous = None #static variable
Run Code Online (Sandbox Code Playgroud)
2)转换为数据帧后将其应用于您的系列
df = pd.DataFrame(s)
df['count'] = df['col'].apply(rolling_count) #new column in dataframe
Run Code Online (Sandbox Code Playgroud)
df的输出
col count
0 B 1
1 B 2
2 A 1
3 A 2
4 A 3
5 B 1
Run Code Online (Sandbox Code Playgroud)