如何用Pandas高效统计连续相同值的起止索引及长度?
最优方案选择:数组循环还是Pandas高效方法?
问题背景
现有Dataframe A 的结构如下:
| Index | 1or0 |
|---|---|
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| ... | ... |
| 8 | 0 |
| 9 | 1 |
| 10 | 1 |
| ... | ... |
需要统计其中连续出现的0或1的起始索引(StartNum)、结束索引(EndNum)及连续次数(Size),生成新Dataframe B,示例结构如下:
| StartNum | EndNum | Size |
|---|---|---|
| 1 | 3 | 3 |
| 8 | 8 | 1 |
| 9 | 10 | 2 |
结论:选Pandas的高效方法,别用数组循环
毫无疑问选Pandas的内置方法,数组循环不仅写起来麻烦、代码啰嗦,遇到大数据集时跑起来慢得离谱——Pandas底层是向量化实现,比Python层面的循环快好几个数量级,完全不是一个量级的效率。
具体实现代码
import pandas as pd # 构造示例Dataframe A(如果原Dataframe的Index是行索引,先转成普通列:df_a = df_a.reset_index().rename(columns={'index': 'Index'})) df_a = pd.DataFrame({ 'Index': [1,2,3,4,5,6,7,8,9,10], '1or0': [0,0,0,0,0,0,0,0,1,1] }) # 给连续相同的1or0值打分组标记 df_a['group'] = (df_a['1or0'] != df_a['1or0'].shift()).cumsum() # 按分组聚合计算所需字段 df_b = df_a.groupby('group').agg( StartNum=('Index', 'first'), EndNum=('Index', 'last'), Size=('Index', 'count') ).reset_index(drop=True) print(df_b)
代码逻辑说明
- 分组标记:用
shift()把1or0列整体下移一行,和原列对比,但凡值不一样就说明是新的连续组的开始,再用cumsum()生成连续的分组ID,把同一段连续值分到同一个组里。 - 聚合计算:按分组ID分组后,直接取每组的第一个Index当StartNum,最后一个Index当EndNum,组内的行数就是连续次数Size,一步到位。
这种方法全程是向量化操作,不用写循环,代码简洁还高效,不管数据集是小样本还是十万百万级的大数据,都能轻松处理。
内容的提问来源于stack exchange,提问作者Natoshi SakiSaki
相关产品推荐
相关产品推荐

