全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Pandas DataFrame中连续行块计数的高效方法

本文将深入探讨如何在pandas dataframe中高效地计算某一列连续相同值的行数,并将其作为新列添加。通过结合`shift()`、`cumsum()`和`groupby().transform('size')`等pandas核心函数,我们将展示一种优雅且强大的解决方案,精确识别并统计数据集中所有连续值块的长度,避免了传统`groupby`的局限性,适用于需要精细化连续数据分析的场景。

在数据处理和分析中,我们经常会遇到需要统计DataFrame中某一列连续相同值出现的次数。例如,给定一个序列 ['a', 'a', 'a', 'b', 'b', 'c', 'd', 'e', 'e', 'e'],我们希望得到的结果是 [3, 3, 3, 2, 2, 1, 1, 3, 3, 3],即每个连续块的长度。这与简单地按值分组并计数不同,因为同一个值在DataFrame中可能非连续地出现多次,而我们只关心连续出现的块。

问题场景与常见误区

假设我们有以下DataFrame:

import pandas as pd

data = {
    'class': ['a', 'a', 'a', 'b', 'b', 'c', 'd', 'e', 'e', 'e', 'f', 'a', 'c', 'd', 'd']
}
df = pd.DataFrame(data)
print("原始DataFrame:")
print(df)

输出:

原始DataFrame:
   class
0      a
1      a
2      a
3      b
4      b
5      c
6      d
7      e
8      e
9      e
10     f
11     a
12     c
13     d
14     d

我们期望的结果是为每行添加一个 consecutive_count 列,其值表示该行所属的连续块的长度:

   class  consecutive_count
0      a                  3
1      a                  3
2      a                  3
3      b                  2
4      b                  2
5      c                  1
6      d                  1
7      e                  3
8      e                  3
9      e                  3
10     f                  1
11     a                  1
12     c                  1
13     d                  2
14     d                  2

误区一:使用 groupby().transform('count')

直接按 class 列进行分组并使用 transform('count') 会统计每个 class 值在整个DataFrame中出现的总次数,而不是连续块的次数。

df['total_count'] = df.groupby('class')['class'].transform('count')
print("\n使用 transform('count') 的结果:")
print(df)

输出:

使用 transform('count') 的结果:
   class  total_count
0      a            4
1      a            4
2      a            4
3      b            2
4      b            2
5      c            2
6      d            3
7      e            3
8      e            3
9      e            3
10     f            1
11     a            4
12     c            2
13     d            3
14     d            3

显然,这不符合我们的需求,例如,第一个 'a' 块有3个,但结果显示为4,因为后面还有一个单独的 'a'。

误区二:使用 (df['class'] != df['class'].shift()).cumsum()

这个表达式可以为每个连续块生成一个唯一的标识符,但它本身不提供块的长度。

df['consecutive_group_id'] = (df['class'] != df['class'].shift()).cumsum()
print("\n使用 cumsum() 生成组ID的结果:")
print(df)

输出:

使用 cumsum() 生成组ID的结果:
   class  consecutive_group_id
0      a                     1
1      a                     1
2      a                     1
3      b                     2
4      b                     2
5      c                     3
6      d                     4
7      e                     5
8      e                     5
9      e                     5
10     f                     6
11     a                     7
12     c                     8
13     d                     9
14     d                     9

这里 consecutive_group_id 成功地将不同的连续块区分开来(例如,第一个 'a' 块的ID是1,而第11行的 'a' 块的ID是7)。这是解决问题的关键一步,但还需要进一步处理才能得到块的长度。

解决方案:组合动态分组与 transform('size')

解决此问题的核心在于创建一个能够同时识别值和其连续性的分组键。我们可以利用 (df['class'] != df['class'].shift()).cumsum() 生成的连续组ID,并将其与原始的 class 值结合起来作为 groupby 的键。

步骤详解:

  1. 识别连续块的起始点:df['class'].shift() 将 class 列向下移动一行,使得当前行的值可以与上一行的值进行比较。 df['class'] != df['class'].shift() 会生成一个布尔序列,True 表示当前行的值与上一行的值不同(即一个新的连续块开始),False 表示相同。对于第一行,shift() 会产生 NaN,与任何值比较都会是 True,这恰好符合其作为第一个块起始点的逻辑。

  2. 生成唯一的连续块ID: 对上述布尔序列应用 .cumsum()。由于 True 在求和时被视为1,False 被视为0,cumsum() 会为每个新的连续块分配一个递增的唯一整数ID。这样,即使同一个值(如 'a')在DataFrame中多次非连续地出现,它们也会被赋予不同的连续块ID。

  3. 构建复合分组键: 现在我们有了两个关键信息:原始的 class 值,以及它所属的连续块的唯一ID。我们将这两者结合起来作为 groupby 的键: df.groupby(['class', (df['class'] != df['class'].shift()).cumsum()]) 这个 groupby 操作会创建一个组,其中每个组都由一个唯一的 (class值, 连续块ID) 对定义。例如,第一个 'a' 块会形成一个组 ('a', 1),而第11行的 'a' 块会形成另一个组 ('a', 7)。

  4. 计算并广播组大小: 在分组之后,我们使用 .transform('size')。transform('size') 的作用是计算每个组的元素数量(即连续块的长度),然后将这个计算结果广播回原始DataFrame中属于该组的所有行。这样,每个属于同一个连续块的行都会得到该块的正确长度。

完整代码示例:

import pandas as pd

# 原始数据
data = {
    'class': ['a', 'a', 'a', 'b', 'b', 'c', 'd', 'e', 'e', 'e', 'f', 'a', 'c', 'd', 'd']
}
df = pd.DataFrame(data)

# 核心解决方案
df['consecutive_count'] = df.groupby(['class', (df['class'] != df['class'].shift()).cumsum()]).transform('size')

print("\n最终结果DataFrame:")
print(df)

输出:

最终结果DataFrame:
   class  consecutive_count
0      a                  3
1      a                  3
2      a                  3
3      b                  2
4      b                  2
5      c                  1
6      d                  1
7      e                  3
8      e                  3
9      e                  3
10     f                  1
11     a                  1
12     c                  1
13     d                  2
14     d                  2

这个结果与我们最初期望的完全一致。

注意事项与总结

  • shift() 处理 NaN: df['class'].shift() 在DataFrame的第一行会产生 NaN。当与 df['class'] 的第一个元素比较时,'a' != NaN 会被评估为 True(在Pandas和Python中,'a' == NaN 是 False),因此 cumsum() 从1开始计数是正确的。
  • 性能: 这种方法利用了Pandas底层的优化,对于大型DataFrame来说效率很高。
  • 通用性: 这种方法不仅适用于字符串类型,也适用于数值型或其他可比较的数据类型。
  • transform() 的强大: transform() 函数是Pandas中一个非常强大的工具,它允许在 groupby 操作后,将聚合结果(如 size, sum, mean 等)广播回原始DataFrame,保持DataFrame的原始形状,这在许多数据转换场景中都非常有用。

通过理解并运用 shift()、cumsum() 和 groupby().transform('size') 的组合,我们能够优雅且高效地解决Pandas DataFrame中连续行块计数的问题,这在时间序列分析、日志处理等领域具有广泛的应用价值。


# python  # 工具 


相关文章: 网站图片在线制作软件,怎么在图片上做链接?  如何快速生成可下载的建站源码工具?  网站设计制作公司地址,网站建设比较好的公司都有哪些?  湖州网站制作公司有哪些,浙江中蓝新能源公司官网?  如何通过虚拟机搭建网站?详细步骤解析  建站之星后台密码遗忘如何找回?  网站网页制作电话怎么打,怎样安装和使用钉钉软件免费打电话?  建站主机CVM配置优化、SEO策略与性能提升指南  平台云上自主建站:模板化设计与智能工具打造高效网站  大型企业网站制作流程,做网站需要注册公司吗?  青岛网站设计制作公司,查询青岛招聘信息的网站有哪些?  网站制作软件免费下载安装,有哪些免费下载的软件网站?  如何在香港免费服务器上快速搭建网站?  如何实现建站之星域名转发设置?  建站之星如何保障用户数据免受黑客入侵?  建站主机选哪家性价比最高?  宁波自助建站系统如何快速打造专业企业网站?  c# F# 的 MailboxProcessor 和 C# 的 Actor 模型  设计网站制作公司有哪些,制作网页教程?  建站之星在线版空间:自助建站+智能模板一键生成方案  家庭建站与云服务器建站,如何选择更优?  定制建站模板如何实现SEO优化与智能系统配置?18字教程  广州网站制作的公司,现在专门做网站的公司有没有哪几家是比较好的,性价比高,模板也多的?  如何使用Golang安装API文档生成工具_快速生成接口文档  如何快速选择适合个人网站的云服务器配置?    济南网站建设制作公司,室内设计网站一般都有哪些功能?  自助网站制作软件,个人如何自助建网站?  免费视频制作网站,更新又快又好的免费电影网站?  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  武汉网站如何制作,黄黄高铁武穴北站途经哪些村庄?  建站之星展会模版如何一键下载生成?  如何在阿里云域名上完成建站全流程?  关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)  家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?  实现点击下箭头变上箭头来回切换的两种方法【推荐】  建站之星展会模板:智能建站与自助搭建高效解决方案  ,石家庄四十八中学官网?  ,柠檬视频怎样兑换vip?  制作网站的基本流程,设计网站的软件是什么?  定制建站流程步骤详解:一站式方案设计与开发指南  建站主机功能解析:服务器选择与快速搭建指南  详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)  陕西网站制作公司有哪些,陕西凌云电器有限公司官网?  西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?  临沂网站制作企业,临沂第三中学官方网站?  清单制作人网站有哪些,近日“兴风作浪的姑奶奶”引起很多人的关注这是什么事情?  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  如何快速搭建二级域名独立网站?  如何彻底卸载建站之星软件? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。