在数据框中,我有一个名为flag的列,我想要计算该列中1的组数。
df=pd.DataFrame({'flag':[1,1,0,1,0,1,1,0,1,1,1]})
df_out=pd.DataFrame({'groups_of_one_count':[4]})
在数据框中,我有一个名为flag的列,我想要计算该列中1的组数。
df=pd.DataFrame({'flag':[1,1,0,1,0,1,1,0,1,1,1]})
df_out=pd.DataFrame({'groups_of_one_count':[4]})
为了提高性能,使用NumPy而没有进行任何追加/连接操作 -
a = df.flag.values
out = (a[1:]>a[:-1]).sum() + (a[0]==1)
说明:我们寻找下一个元素大于前一个元素。如果满足条件,则信号开始一个岛屿/组的1s
。我们仅将求和作为最终输出。对于特殊情况,当这样的一组从第一个元素开始时,我们将其单独捕获。
给定示例的时间按比例缩放10000x
-
In [64]: df=pd.DataFrame({'flag':[1,1,0,1,0,1,1,0,1,1,1]})
In [65]: df = pd.concat([df]*10000)
# @Quang Hoang's soln
In [66]: %timeit (np.diff(np.append(df.flag.values,0)) == -1).sum()
362 µs ± 26.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# From this post
In [67]: %%timeit
...: a = df.flag.values
...: out = (a[1:]>a[:-1]).sum() + (a[0]==1)
191 µs ± 5.4 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# @jezrael's soln
In [68]: %timeit (df['flag'].ne(df['flag'].shift()) & df['flag'].eq(1)).sum()
1.39 ms ± 8.86 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# @YOBEN_S's soln
In [69]: %timeit df[df.flag.ne(0)].index.to_series().diff().ne(1).sum()
2.92 ms ± 209 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
解决方案将会进行修改,变为获取要搜索的数字的掩码(这里是1
),并对其进行操作 -
a = df.flag.values
m = a==1
out = (m[1:] & ~m[:-1]).sum() + m[0]
这个想法是使用ne
(不相等)逐一比较元素组,并利用Series.shift
方法筛选出仅包含组中有 1
的组:
a = (df['flag'].ne(df['flag'].shift()) & df['flag'].eq(1)).sum()
print (a)
4
df_out=pd.DataFrame({'groups_of_one_count':[a]})
print (df_out)
groups_of_one_count
0 4
详情:
print (df.assign(consec=df['flag'].ne(df['flag'].shift()),
eq1 = df['flag'].eq(1),
chained = (df['flag'].ne(df['flag'].shift()) & df['flag'].eq(1))
))
flag consec eq1 chained
0 1 True True True
1 1 False True False
2 0 True False False
3 1 True True True
4 0 True False False
5 1 True True True
6 1 False True False
7 0 True False False
8 1 True True True
9 1 False True False
10 1 False True False
使用纯 NumPy 可以提高性能:
(np.diff(np.append(df.flag.values,0)) == -1).sum()
想法: 统计数据从1
到0
跳转的次数。我们使用np.append
为以1
结尾的系列添加一个后续的0
,以便包含最后一个块。
首先,我们选择不等于0的index
,然后找到diff
的索引。如果diff
不连续(这里不等于1),那就是不同的组:
df[df.flag.ne(0)].index.to_series().diff().ne(1).sum()
4
df.flag[0]
。此外,+a[0]
就足够了,而且比+ (a[0]==1)
快一点。 - Quang Hoang