如何计算 Pandas 系列中重复出现的相同值
How to count recurring identical values in a Pandas Series
我有一个具有 True/False 个值的 Pandas 系列,我需要计算与前一个值相同的值出现的频率。
每当值发生变化时,计数应从 1 重新开始。
pd.Series([True, False, False, False, True, True, False])
0 True --> 1
1 False --> 1
2 False --> 2
3 False --> 3
4 True --> 1
5 True --> 2
6 False --> 1
dtype: bool
我尝试了 shift() 和 cumsum() 的各种组合,但没有成功。
有什么提示吗?
麦酒
您可以使用比较 shift
ed values and cumsum
and use it for cumcount
:
按连续值创建组
s = pd.Series([True, False, False, False, True, True, False])
s1 = s.groupby(s.ne(s.shift()).cumsum()).cumcount().add(1)
print (s1)
0 1
1 1
2 2
3 3
4 1
5 2
6 1
dtype: int64
详情:
print (s.ne(s.shift()).cumsum())
0 1
1 2
2 2
3 2
4 3
5 3
6 4
dtype: int32
另一个解决方案是分别计算True
s和False
s然后求和输出:
cm1 = s.cumsum()
s1 = cm1-cm1.where(~s).ffill().fillna(0)
cm2 = (~s).cumsum()
s2 = cm2-cm2.where(s).ffill().fillna(0)
s3 = s1.add(s2).astype(int)
print (s3)
0 1
1 1
2 2
3 3
4 1
5 2
6 1
dtype: int32
详情:
print (s1)
0 1.0
1 0.0
2 0.0
3 0.0
4 1.0
5 2.0
6 0.0
dtype: float64
print (s2)
0 0.0
1 1.0
2 2.0
3 3.0
4 0.0
5 0.0
6 1.0
dtype: float64
计时:
np.random.seed(2018)
N = 1000000
s = pd.Series(np.random.choice([True, False], N))
#print (s)
def jez1(s):
return s.groupby(s.ne(s.shift()).cumsum()).cumcount().add(1)
def jez2(s):
cm1 = s.cumsum()
s1 = cm1-cm1.where(~s).ffill().fillna(0)
cm2 = (~s).cumsum()
s2 = cm2-cm2.where(s).ffill().fillna(0)
return s1.add(s2).astype(int)
print (jez1(s))
print (jez2(s))
In [173]: %timeit jez1(s)
1 loop, best of 3: 199 ms per loop
In [174]: %timeit jez2(s)
10 loops, best of 3: 92 ms per loop
我有一个具有 True/False 个值的 Pandas 系列,我需要计算与前一个值相同的值出现的频率。
每当值发生变化时,计数应从 1 重新开始。
pd.Series([True, False, False, False, True, True, False])
0 True --> 1
1 False --> 1
2 False --> 2
3 False --> 3
4 True --> 1
5 True --> 2
6 False --> 1
dtype: bool
我尝试了 shift() 和 cumsum() 的各种组合,但没有成功。
有什么提示吗?
麦酒
您可以使用比较 shift
ed values and cumsum
and use it for cumcount
:
s = pd.Series([True, False, False, False, True, True, False])
s1 = s.groupby(s.ne(s.shift()).cumsum()).cumcount().add(1)
print (s1)
0 1
1 1
2 2
3 3
4 1
5 2
6 1
dtype: int64
详情:
print (s.ne(s.shift()).cumsum())
0 1
1 2
2 2
3 2
4 3
5 3
6 4
dtype: int32
另一个解决方案是分别计算True
s和False
s然后求和输出:
cm1 = s.cumsum()
s1 = cm1-cm1.where(~s).ffill().fillna(0)
cm2 = (~s).cumsum()
s2 = cm2-cm2.where(s).ffill().fillna(0)
s3 = s1.add(s2).astype(int)
print (s3)
0 1
1 1
2 2
3 3
4 1
5 2
6 1
dtype: int32
详情:
print (s1)
0 1.0
1 0.0
2 0.0
3 0.0
4 1.0
5 2.0
6 0.0
dtype: float64
print (s2)
0 0.0
1 1.0
2 2.0
3 3.0
4 0.0
5 0.0
6 1.0
dtype: float64
计时:
np.random.seed(2018)
N = 1000000
s = pd.Series(np.random.choice([True, False], N))
#print (s)
def jez1(s):
return s.groupby(s.ne(s.shift()).cumsum()).cumcount().add(1)
def jez2(s):
cm1 = s.cumsum()
s1 = cm1-cm1.where(~s).ffill().fillna(0)
cm2 = (~s).cumsum()
s2 = cm2-cm2.where(s).ffill().fillna(0)
return s1.add(s2).astype(int)
print (jez1(s))
print (jez2(s))
In [173]: %timeit jez1(s)
1 loop, best of 3: 199 ms per loop
In [174]: %timeit jez2(s)
10 loops, best of 3: 92 ms per loop