0

0

使用 Pandas 高效处理分组数据:基于条件和日期排序创建新列

霞舞

霞舞

发布时间:2025-08-07 21:02:13

|

455人浏览过

|

来源于php中文网

原创

使用 pandas 高效处理分组数据:基于条件和日期排序创建新列

本文详细介绍了如何利用 Pandas 库处理复杂的分组数据操作。我们将学习如何结合 groupby、apply、sort_values、shift 和 cumsum 等方法,根据特定条件(如日期降序和数值变化)为 DataFrame 添加新列。教程将通过一个实际案例,演示如何高效地实现基于组内逻辑的条件累积计算,并确保结果正确对齐到原始数据结构。

引言

在数据分析和处理中,我们经常需要根据特定分组内的逻辑来生成新的数据列。这些逻辑可能涉及排序、条件判断以及累积计算。Pandas 提供了强大且灵活的工具集来应对此类挑战。本教程将以一个具体的案例为例,展示如何在一个 DataFrame 中,根据 text 列进行分组,然后根据 date 列的降序以及 number 列的数值变化,计算并添加一个名为 test 的新列。

问题描述

假设我们有以下 Pandas DataFrame:

import pandas as pd
import numpy as np

data = {
    'id': [1, 2, 3, 4, 5, 6, 7],
    'date': ['2019-02-01', '2019-02-10', '2019-02-25', '2019-03-05', '2019-03-16', '2019-04-05', '2019-05-15'],
    'date_difference': [None, 9, 15, 11, 10, 19, 40],
    'number': [1, 0, 1, 0, 0, 0, 0],
    'text': ['A', 'A', 'A', 'A', 'A', 'B', 'B']
}

df = pd.DataFrame(data)

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

原始 DataFrame 如下所示:

id date date_difference number text
1 2019-02-01 NULL 1 A
2 2019-02-10 9 0 A
3 2019-02-25 15 1 A
4 2019-03-05 11 0 A
5 2019-03-16 10 0 A
6 2019-04-05 19 0 B
7 2019-05-15 40 0 B

我们的目标是根据 text 列进行分组,并在每个组内,依据 date 列的降序,生成一个名为 test 的新列。生成 test 列的规则如下:

  • 在每个组内,从日期降序排列的第一个条目开始计算。
  • 当 number 列的值为 0 时,步长(step size)初始为 1。
  • 当遇到 number 列的值为 1 时,步长增加 1。
  • 如果组内 number 列中没有 1,则整个组的步长始终保持为 1。

期望的最终 DataFrame 如下:

id date date_difference number text test
1 2019-02-01 NULL 1 A 2
2 2019-02-10 9 0 A 2
3 2019-02-25 15 1 A 1
4 2019-03-05 11 0 A 1
5 2019-03-16 10 0 A 1
6 2019-04-05 19 0 B 1
7 2019-05-15 40 0 B 1

解决方案实现

解决此问题的关键在于正确地结合 Pandas 的分组、排序、位移和累积求和操作。

堆友
堆友

Alibaba Design打造的设计师全成长周期服务平台,旨在成为设计师的好朋友

下载

核心思路

  1. 分组 (Group by): 首先,我们需要根据 text 列对 DataFrame 进行分组,因为 test 列的计算逻辑是针对每个 text 组独立的。
  2. 组内排序 (Sort within group): 问题的关键在于“从日期降序开始计算”。这意味着在每个组内部,我们需要先按 date 列降序排列数据,然后进行计算。
  3. 位移 (Shift): 为了实现“当 number == 0 时步长为 1,当找到 1 时步长增加 1”的逻辑,我们可以将 number 列进行位移操作。将 number 列向前位移一位,并用 1 填充位移后产生的第一个缺失值。这样,对于原始 number 为 0 的行,其对应的位移后值通常是其下一个条目的 number 值;而对于原始 number 为 1 的行,其对应的位移后值会影响其之前的行的计算。fill_value=1 确保了序列的起始值(即日期降序的第一个值)为 1,符合“步长初始为 1”的条件。
  4. 累积求和 (Cumulative Sum): 对位移后的 number 列进行累积求和,即可得到所需的 test 值。这个累积和会根据 number 列中的 1 进行递增。
  5. 结果对齐 (Align Results): groupby().apply() 返回的结果通常会保留原始 DataFrame 的索引,但如果内部进行了排序,则需要确保最终结果能正确地与原始 DataFrame 对齐。assign() 方法在这里非常有用,它能自动根据索引将新生成的 Series 与原 DataFrame 合并。

完整代码

import pandas as pd
import numpy as np

data = {
    'id': [1, 2, 3, 4, 5, 6, 7],
    'date': ['2019-02-01', '2019-02-10', '2019-02-25', '2019-03-05', '2019-03-16', '2019-04-05', '2019-05-15'],
    'date_difference': [None, 9, 15, 11, 10, 19, 40],
    'number': [1, 0, 1, 0, 0, 0, 0],
    'text': ['A', 'A', 'A', 'A', 'A', 'B', 'B']
}

df = pd.DataFrame(data)

# 将 'date' 列转换为 datetime 类型,以便正确排序
df['date'] = pd.to_datetime(df['date'])

# 使用 assign 方法添加新列 'test'
df_result = df.assign(
    test=df
    # 1. 按 'text' 列进行分组
    .groupby("text")
    # 2. 对每个组应用一个函数
    .apply(
        lambda g: (
            # 3. 在组内按 'date' 列降序排序
            g.sort_values(by="date", ascending=False)
            # 4. 对 'number' 列进行位移,向前一位,并用 1 填充缺失值
            .number.shift(periods=1, fill_value=1)
            # 5. 对位移后的结果进行累积求和
            .cumsum()
        )
    )
    # 6. 移除 apply 产生的 'text' 索引层,使 Series 索引与原始 df 索引一致
    .droplevel("text")
    # assign 方法会自动将结果 Series 与原始 DataFrame 的索引对齐
)

print("\n最终 DataFrame:")
print(df_result)

逻辑解析与示例跟踪

让我们以 text 为 'A' 的组为例,详细解释每一步的操作:

原始 text='A' 的数据(按原始索引顺序):

id date number
1 2019-02-01 1
2 2019-02-10 0
3 2019-02-25 1
4 2019-03-05 0
5 2019-03-16 0
  1. g.sort_values(by="date", ascending=False): 将组内数据按 date 降序排列。 排序后的数据(索引为原始 DataFrame 索引):

    id date number
    5 2019-03-16 0
    4 2019-03-05 0
    3 2019-02-25 1
    2 2019-02-10 0
    1 2019-02-01 1
  2. .number.shift(periods=1, fill_value=1): 对排序后的 number 列 [0, 0, 1, 0, 1] 进行向前位移,并用 1 填充第一个位置。 位移后的 Series: [1, 0, 0, 1, 0] (对应索引 [5, 4, 3, 2, 1])

  3. .cumsum(): 对位移后的 Series [1, 0, 0, 1, 0] 进行累积求和。 累积和结果: [1, 1, 1, 2, 2] (对应索引 [5, 4, 3, 2, 1])

    这意味着:

    • df.loc[5, 'test'] = 1
    • df.loc[4, 'test'] = 1
    • df.loc[3, 'test'] = 1
    • df.loc[2, 'test'] = 2
    • df.loc[1, 'test'] = 2
  4. .droplevel("text"): apply 方法在返回 Series 时,如果 groupby 包含多个键或 apply 的结果不是单个 Series,可能会产生 MultiIndex。在这里,apply 内部返回的是一个 Series,其索引是原始 DataFrame 的索引,但由于 groupby("text"),其上会有一个 text 层的 MultiIndex。droplevel("text") 移除了这个额外的索引层,使得最终 Series 的索引与原始 df 的索引完全匹配。

  5. df.assign(test=...): assign 方法将这个计算好的 Series 作为 test 列添加到原始 df 中。Pandas 会自动根据索引进行对齐,确保 test 值回到其原始的行位置。

最终结果与期望输出完全一致。对于 text='B' 的组,由于 number 列中没有 1,shift(fill_value=1) 会使所有值变为 1,cumsum() 结果也都是 1,符合“没有 1 时步长保持为 1”的规则。

注意事项与总结

  • 日期类型转换: 在进行日期排序之前,确保 date 列的数据类型是 datetime。如果不是,需要使用 pd.to_datetime() 进行转换。
  • groupby().apply() 的灵活性: apply() 方法非常强大,允许你在每个分组上执行几乎任何自定义操作。但需要注意其性能可能不如优化的 Pandas 方法(如 transform 或 agg),对于大型数据集应谨慎使用。然而,对于这种复杂的、需要组内排序和

相关专题

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

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

51

2025.12.04

数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

299

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

220

2025.10.31

sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

383

2023.09.04

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

533

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

10

2026.01.06

C++类型转换方式
C++类型转换方式

本专题整合了C++类型转换相关内容,想了解更多相关内容,请阅读专题下面的文章。

294

2025.07.15

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

3

2026.01.09

热门下载

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

精品课程

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

共58课时 | 3.4万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

ASP 教程
ASP 教程

共34课时 | 3.3万人学习

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

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