0

0

Pandas技巧:高效处理连续相同值分组并计算最大值

霞舞

霞舞

发布时间:2025-08-04 21:24:01

|

695人浏览过

|

来源于php中文网

原创

Pandas技巧:高效处理连续相同值分组并计算最大值

本文详细介绍了在Pandas中如何高效地识别并处理数据框中连续相同的分组,并针对这些分组计算指定列的最大值。通过巧妙运用shift()、ne()和cumsum()组合创建连续分组ID,并结合groupby()和transform()方法,实现精确的组内最大值计算,避免了传统循环和错误条件判断带来的问题,极大提升了数据处理的效率和准确性。

在数据分析中,我们经常会遇到需要对数据框中连续出现相同值的行进行分组,并对每个这样的连续分组执行聚合操作(如求最大值、最小值、平均值等)的需求。这种“连续分组”的需求与简单的按某一列值分组有所不同,它强调的是值的“相邻性”。

常见误区与挑战

初学者在处理这类问题时,往往会尝试使用循环或复杂的条件判断来解决。例如,考虑以下原始数据:

import pandas as pd

data = {
    'Fruits': ['Apple', 'Apple', 'Banana', 'Orange', 'Apple', 'Apple'],
    'Price': [20, 30, 50, 170, 55, 90]
}

df = pd.DataFrame(data)

期望的结果是,第一组连续的“Apple”行(索引0和1)的Max值为30,第二组连续的“Apple”行(索引4和5)的Max值为90。

一种常见的尝试可能类似于以下代码:

# 初始尝试(存在问题)
df['Max'] = 0.0
for x in range(0, df.shape[0]):
    condition = (df['Fruits'] == "Apple") & (df['Fruits'].shift(-1) == "Apple") | (df['Fruits'].shift(1) == "Apple")
    df.loc[condition, 'Max'] = df.loc[condition, 'Price'].max()

这段代码存在几个主要问题:

  1. 效率低下: 使用for循环遍历DataFrame行在Pandas中通常不是最佳实践,尤其对于大数据集。
  2. 条件逻辑错误: condition的判断逻辑过于宽泛。例如,df['Fruits'].shift(1)=="Apple"会使得索引为2的'Banana'行也满足条件(因为其上一行是'Apple'),从而被包含在筛选中。
  3. 聚合范围不准确: df.loc[condition,'Price'].max()是在所有满足condition的行中计算一个全局最大值,而不是针对每个独立的连续分组。这导致所有满足条件的行都被赋予了同一个最大值(例如,示例中'Banana'行也被错误地赋予了90.0)。

为了克服这些问题,我们需要一种更Pandas化、更高效且逻辑更严谨的方法来识别并处理连续分组。

构建连续分组标识

解决连续分组问题的关键在于为每个连续的相同值块生成一个唯一的标识符。Pandas提供了强大的工具来完成这一任务,核心思想是利用shift()、ne()和cumsum()的组合。

  1. df['Fruits'].shift(): 创建一个新Series,其中每个元素是原Series中前一行的值。这使得我们可以比较当前行和前一行的值。
  2. df['Fruits'].ne(df['Fruits'].shift()): ne()代表“不等于”。这个操作会返回一个布尔Series,当当前行的值与前一行的值不同时为True,否则为False。这意味着每当一个连续块的起始点(即值发生变化)时,就会出现一个True。
  3. .cumsum(): cumsum()是累积求和。当应用于布尔Series时,True被视为1,False被视为0。因此,每遇到一个True(即一个新连续块的开始),累积和就会增加1。这样,同一个连续块内的所有行将拥有相同的累积和值,从而形成一个完美的连续分组ID。

让我们通过一个例子来理解这个过程:

df = pd.DataFrame({
    'Fruits': ['Apple', 'Apple', 'Banana', 'Orange', 'Apple', 'Apple'],
    'Price': [20, 30, 50, 170, 55, 90]
})

# 步骤1: 检查当前行与前一行是否不同
# df.Fruits.shift() -> [NaN, 'Apple', 'Apple', 'Banana', 'Orange', 'Apple']
# df.Fruits.ne(df.Fruits.shift()) -> [True, False, True, True, True, False] (NaN在ne中被视为不同)

# 步骤2: 累积求和生成分组ID
grp = df.Fruits.ne(df.Fruits.shift()).cumsum()
print(grp)

输出的grp Series将是:

Stenography
Stenography

一个AI驱动的代码库API

下载
0    1
1    1
2    2
3    3
4    4
5    4
Name: Fruits, dtype: int64

可以看到,grp成功地为第一组“Apple”生成了ID 1,为“Banana”生成了ID 2,为“Orange”生成了ID 3,为第二组“Apple”生成了ID 4。这正是我们所需的连续分组标识。

应用组内聚合与结果回填

有了连续分组标识grp,我们就可以使用Pandas的groupby()方法进行分组聚合。为了将聚合结果(例如最大值)“回填”到原始DataFrame的相应行中,我们需要使用transform()方法,而不是agg()或apply()。

  • df.groupby(grp): 按照我们刚刚创建的grp Series进行分组。
  • ['Price']: 选择我们希望聚合的列,这里是Price。
  • .transform('max'): 这是关键一步。transform()方法会对每个分组执行指定的聚合操作(这里是max),然后将结果广播回原始DataFrame的形状,确保每个原始行都对应其所属分组的聚合结果。这与agg()或apply()不同,它们通常会返回一个聚合后的Series,其索引是分组键。

将这些步骤整合起来,完整的解决方案如下:

import pandas as pd

data = {
    'Fruits': ['Apple', 'Apple', 'Banana', 'Orange', 'Apple', 'Apple'],
    'Price': [20, 30, 50, 170, 55, 90]
}

df = pd.DataFrame(data)

# 1. 构建连续分组标识
grp = df.Fruits.ne(df.Fruits.shift()).cumsum()

# 2. 对连续分组进行聚合,并使用transform将结果回填
df['Max'] = df.groupby(grp)['Price'].transform('max')

print(df)

输出结果:

   Fruits  Price  Max
0   Apple     20   30
1   Apple     30   30
2  Banana     50   50
3  Orange    170  170
4   Apple     55   90
5   Apple     90   90

结果分析:

  • 对于索引0和1的“Apple”行,Max值是其所在连续分组的最大价格30。
  • 对于索引2的“Banana”行,Max值是其所在连续分组的最大价格50。
  • 对于索引3的“Orange”行,Max值是其所在连续分组的最大价格170。
  • 对于索引4和5的“Apple”行,Max值是其所在连续分组的最大价格90。

这个结果完全符合我们的预期,并且通过Pandas的向量化操作实现了高效计算。

注意事项与扩展

  1. 通用性: 这种方法不仅适用于计算最大值,也适用于其他聚合函数,如min()、mean()、sum()、count()等。只需将transform('max')替换为相应的聚合函数即可。
  2. 适用于任何列: Fruits列可以替换为DataFrame中的任何其他列,只要该列是您希望进行连续分组的依据。
  3. 效率优势: 相比于使用for循环或apply自定义函数,groupby().transform()结合shift().ne().cumsum()是处理这类问题的推荐方法,因为它充分利用了Pandas底层的优化,性能表现优异。
  4. 初始NaN处理: df.Fruits.shift()在Series的第一个位置会产生NaN。ne()方法能够正确处理NaN,将其视为与任何非NaN值不同,因此第一个元素总是会触发True,确保第一个连续块被正确识别。

总结

在Pandas中处理按连续相同值分组并进行聚合的需求时,核心在于巧妙地构建连续分组的标识符。通过df[column].ne(df[column].shift()).cumsum()的组合,我们可以高效地生成这些标识符。随后,利用df.groupby(group_id)[value_column].transform(aggregate_function),可以精准地将聚合结果回填到原始DataFrame的对应行中。掌握这一技巧,将极大地提升您在Pandas中处理复杂数据分组问题的能力。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

56

2025.12.04

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.11.20

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

183

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

286

2024.02.23

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

258

2025.06.11

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

123

2025.08.07

数据分析的方法
数据分析的方法

数据分析的方法有:对比分析法,分组分析法,预测分析法,漏斗分析法,AB测试分析法,象限分析法,公式拆解法,可行域分析法,二八分析法,假设性分析法。php中文网为大家带来了数据分析的相关知识、以及相关文章等内容。

471

2023.07.04

数据分析方法有哪几种
数据分析方法有哪几种

数据分析方法有:1、描述性统计分析;2、探索性数据分析;3、假设检验;4、回归分析;5、聚类分析。本专题为大家提供数据分析方法的相关的文章、下载、课程内容,供大家免费下载体验。

280

2023.08.07

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

9

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.2万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.0万人学习

ASP 教程
ASP 教程

共34课时 | 4.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号