在数据分析中,我们经常会遇到需要对数据框中连续出现相同值的行进行分组,并对每个这样的连续分组执行聚合操作(如求最大值、最小值、平均值等)的需求。这种“连续分组”的需求与简单的按某一列值分组有所不同,它强调的是值的“相邻性”。
初学者在处理这类问题时,往往会尝试使用循环或复杂的条件判断来解决。例如,考虑以下原始数据:
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()
这段代码存在几个主要问题:
为了克服这些问题,我们需要一种更Pandas化、更高效且逻辑更严谨的方法来识别并处理连续分组。
解决连续分组问题的关键在于为每个连续的相同值块生成一个唯一的标识符。Pandas提供了强大的工具来完成这一任务,核心思想是利用shift()、ne()和cumsum()的组合。
让我们通过一个例子来理解这个过程:
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将是:
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()。
将这些步骤整合起来,完整的解决方案如下:
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
结果分析:
这个结果完全符合我们的预期,并且通过Pandas的向量化操作实现了高效计算。
在Pandas中处理按连续相同值分组并进行聚合的需求时,核心在于巧妙地构建连续分组的标识符。通过df[column].ne(df[column].shift()).cumsum()的组合,我们可以高效地生成这些标识符。随后,利用df.groupby(group_id)[value_column].transform(aggregate_function),可以精准地将聚合结果回填到原始DataFrame的对应行中。掌握这一技巧,将极大地提升您在Pandas中处理复杂数据分组问题的能力。
以上就是Pandas技巧:高效处理连续相同值分组并计算最大值的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号