0

0

Pandas数据框中按组比较相邻行数据并生成新列的教程

聖光之護

聖光之護

发布时间:2025-09-21 21:45:01

|

587人浏览过

|

来源于php中文网

原创

Pandas数据框中按组比较相邻行数据并生成新列的教程

本教程详细介绍了如何在Pandas数据框中,根据特定分组(如Race_ID),比较当前行C_k列的值与下一行adv列的值。我们将探讨两种高效的方法来找出满足条件的第一个C_k值,并将其填充到一个新列C_t中,同时处理无匹配项时的默认值设定,以实现复杂的跨行条件逻辑。

引言:问题背景与目标

在数据分析实践中,我们经常需要处理涉及跨行比较和分组聚合的复杂逻辑。例如,在一个按比赛id和日期降序排列的数据集中,我们可能需要为每个比赛(race_id)确定一个特定的c_k值。这个c_k值的定义是:在该race_id组内,找到第一个满足条件 adv_(n+1)

这是一个典型的Pandas分组操作与行间比较结合的问题,需要灵活运用groupby、shift、条件筛选和值填充等功能。

数据准备

首先,我们创建一个示例Pandas DataFrame来模拟比赛数据,其中包含Race_ID、Date、adv和C_k列。

import pandas as pd
import io

data = """Race_ID   Date           adv          C_k
1         1/1/2023       2.5          2.7     
1         1/1/2023       1.4          2.6     
1         1/1/2023       1.3          1.9     
1         1/1/2023       1.1          1.2     
2         11/9/2022      1.4          1.1     
2         11/9/2022      1.3          1.2     
2         11/9/2022      1.0          0.4     
3         17/4/2022      0.9          0.2     
3         17/4/2022      0.8          0.4     
3         17/4/2022      0.7          0.5     
3         17/4/2022      0.6          0.2     
3         17/4/2022      0.5          0.4     
"""

df = pd.read_csv(io.StringIO(data), sep=r'\s\s+', engine='python')
df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y')

print("原始DataFrame:")
print(df)

原始DataFrame:

    Race_ID       Date  adv  C_k
0         1 2023-01-01  2.5  2.7
1         1 2023-01-01  1.4  2.6
2         1 2023-01-01  1.3  1.9
3         1 2023-01-01  1.1  1.2
4         2 2022-09-11  1.4  1.1
5         2 2022-09-11  1.3  1.2
6         2 2022-09-11  1.0  0.4
7         3 2022-04-17  0.9  0.2
8         3 2022-04-17  0.8  0.4
9         3 2022-04-17  0.7  0.5
10        3 2022-04-17  0.6  0.2
11        3 2022-04-17  0.5  0.4

方法一:条件筛选、去重与映射

这种方法的核心思想是:首先识别所有满足条件的行,然后从这些行中为每个组提取出我们所需的C_k值,最后将这些值映射回原始DataFrame。

核心步骤:

  1. 获取下一行的adv值:使用groupby('Race_ID')['adv'].shift(-1),在每个组内将adv列向下平移一位,从而获取下一行的adv值。
  2. 构建布尔条件:将平移后的adv值与当前行的C_k值进行比较(
  3. 筛选符合条件的行:使用布尔索引从原始DataFrame中筛选出所有满足条件的行。
  4. 提取目标C_k值:由于题目要求的是第一个满足条件的C_k值(即min{n| adv_(n+1)
  5. 映射与填充:将提取出的C_k值映射回原始DataFrame的Race_ID列,并使用fillna(1)处理那些没有找到匹配C_k值的组。

代码示例:

# 步骤1 & 2: 获取下一行的adv值并构建布尔条件
# df.groupby('Race_ID')['adv'].shift(-1) 获取每个组中下一行的adv值
# .le(df['C_k']) 比较下一行的adv是否小于等于当前行的C_k
condition = df.groupby('Race_ID')['adv'].shift(-1).le(df['C_k'])

# 步骤3 & 4: 筛选符合条件的行,然后去重以获取每个Race_ID的最后一个符合条件的C_k
# df[condition] 筛选出所有满足条件的行
# .drop_duplicates(subset=['Race_ID'], keep='last') 对于每个Race_ID,保留最后出现的行
# .set_index('Race_ID')['C_k'] 将Race_ID设为索引,并选择C_k列,生成一个Series
s = (df[condition]
     .drop_duplicates(subset=['Race_ID'], keep='last')
     .set_index('Race_ID')['C_k'])

# 步骤5: 映射并填充新列
# df['Race_ID'].map(s) 将Series s中的值根据Race_ID映射到新列
# .fillna(1) 对于没有匹配到的Race_ID(即s中不存在的Race_ID),填充默认值1
df['C_t_method1'] = df['Race_ID'].map(s).fillna(1)

print("\n方法一结果DataFrame:")
print(df)

结果DataFrame (方法一):

唱鸭
唱鸭

音乐创作全流程的AI自动作曲工具,集 AI 辅助作词、AI 自动作曲、编曲、混音于一体

下载
    Race_ID       Date  adv  C_k  C_t_method1
0         1 2023-01-01  2.5  2.7          1.9
1         1 2023-01-01  1.4  2.6          1.9
2         1 2023-01-01  1.3  1.9          1.9
3         1 2023-01-01  1.1  1.2          1.9
4         2 2022-09-11  1.4  1.1          1.2
5         2 2022-09-11  1.3  1.2          1.2
6         2 2022-09-11  1.0  0.4          1.2
7         3 2022-04-17  0.9  0.2          1.0
8         3 2022-04-17  0.8  0.4          1.0
9         3 2022-04-17  0.7  0.5          1.0
10        3 2022-04-17  0.6  0.2          1.0
11        3 2022-04-17  0.5  0.4          1.0

注意事项: drop_duplicates(keep='last') 在此处的关键作用是,由于我们寻找的是min{n| adv_(n+1) 位置靠后的行。由于原始数据是按日期降序排列的,这意味着位置靠后的行对应的n值更小(即更早满足条件),因此keep='last'是正确的选择。

方法二:条件赋值与组内变换

这种方法利用Series.where()进行条件性赋值,然后通过groupby().transform('last')将组内的最后一个非NaN值广播到整个组。

核心步骤:

  1. 条件性地保留C_k值:同样使用shift(-1)获取下一行的adv值,并构建布尔条件。然后,使用Series.where()函数,只有当条件为True时才保留C_k的原始值,否则将其替换为NaN。
  2. 组内向下填充最后一个有效值:对处理后的C_k列按Race_ID分组,并使用transform('last')。transform('last')会将每个组中最后一个非NaN的值填充到该组的所有行中。
  3. 填充默认值:最后,使用fillna(1)处理那些整个组都没有满足条件(即transform后仍然是NaN)的行。

代码示例:

# 步骤1: 条件性地保留C_k值
# df['C_k'].where(...) 只有当条件为True时保留C_k的值,否则为NaN
temp_C_k = df['C_k'].where(df.groupby('Race_ID')['adv'].shift(-1).le(df['C_k']))

# 步骤2: 组内向下填充最后一个有效值
# .groupby(df['Race_ID']).transform('last') 对每个Race_ID组,获取最后一个非NaN的值,并广播到整个组
transformed_C_k = temp_C_k.groupby(df['Race_ID']).transform('last')

# 步骤3: 填充默认值
df['C_t_method2'] = transformed_C_k.fillna(1)

print("\n方法二结果DataFrame:")
print(df)

结果DataFrame (方法二):

    Race_ID       Date  adv  C_k  C_t_method1  C_t_method2
0         1 2023-01-01  2.5  2.7          1.9          1.9
1         1 2023-01-01  1.4  2.6          1.9          1.9
2         1 2023-01-01  1.3  1.9          1.9          1.9
3         1 2023-01-01  1.1  1.2          1.9          1.9
4         2 2022-09-11  1.4  1.1          1.2          1.2
5         2 2022-09-11  1.3  1.2          1.2          1.2
6         2 2022-09-11  1.0  0.4          1.2          1.2
7         3 2022-04-17  0.9  0.2          1.0          1.0
8         3 2022-04-17  0.8  0.4          1.0          1.0
9         3 2022-04-17  0.7  0.5          1.0          1.0
10        3 2022-04-17  0.6  0.2          1.0          1.0
11        3 2022-04-17  0.5  0.4          1.0          1.0

两种方法比较与选择

  • 可读性与简洁性:方法二(使用where和transform)通常被认为在代码结构上更为流畅和简洁,因为它使用了链式操作,减少了中间变量的创建。
  • 性能:对于大多数中等规模的数据集,两种方法的性能差异不显著。在处理非常大的数据集时,Pandas的优化通常使得transform操作非常高效,因为它是在C语言层面实现的。方法一涉及创建临时DataFrame和进行多次索引操作,理论上可能略慢,但实际差异需通过性能测试确认。
  • 灵活性:两种方法都非常灵活,可以适应不同的条件逻辑和填充策略。选择哪种方法更多取决于个人偏好和团队的代码风格。

总结

本教程展示了在Pandas数据框中处理复杂分组和跨行比较问题的两种高效策略。无论是通过条件筛选、去重与映射,还是通过条件赋值与组内变换,Pandas都提供了强大且灵活的工具集来解决这类数据操作挑战。理解groupby()、shift()、where()、transform()

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

379

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

607

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

348

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

255

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

583

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

519

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

631

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

595

2023.09.22

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Django 教程
Django 教程

共28课时 | 2.6万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.0万人学习

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

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