0

0

Pandas DataFrame中基于指定日期进行数据聚合与分析

碧海醫心

碧海醫心

发布时间:2025-08-14 20:50:24

|

1033人浏览过

|

来源于php中文网

原创

Pandas DataFrame中基于指定日期进行数据聚合与分析

本教程详细介绍了如何使用Pandas在DataFrame中根据每行指定的日期,将其他日期列的数值分别聚合为“之前”和“之后”的总和。通过数据重塑(melt)、条件判断、分组聚合(groupby)和合并(merge)等步骤,高效地实现这一复杂的数据分析需求,为时间序列数据的灵活处理提供了实用方法。

在数据分析中,我们经常会遇到需要根据特定条件对数据进行动态聚合的场景。例如,在一个包含多个日期列和一行特定日期列的dataframe中,我们可能需要计算每个实体在指定日期之前和之后所有数值的总和。本教程将详细阐述如何利用pandas的强大功能,高效地完成这一任务。

1. 数据准备与问题理解

假设我们有一个DataFrame,其中包含一个标识符列(如Code)、一个指定日期列(Date),以及一系列以日期命名的数值列。我们的目标是为每一行计算:

  • 所有日期列中,日期早于或等于该行Date列值的数值总和(Before)。
  • 所有日期列中,日期晚于该行Date列值的数值总和(After)。

为了便于演示,我们首先创建一个示例DataFrame:

import pandas as pd
import numpy as np

# 创建示例数据
data = {
    'Code': ['12345', '12346', '12347'],
    '202001': [1000, 999, 1983],
    '202002': [1001, 1000, 1984],
    '202003': [1002, 1001, 1985],
    '202004': [1003, 1002, 1986],
    '202005': [1004, 1003, 1987],
    '202006': [1005, 1003, 1988],
    '202007': [3006, 1005, 1989],
    '202008': [1007, 1006, 1990],
    '202009': [1008, 1007, 1991],
    '202010': [1009, 1008, 1992],
    '202011': [1010, 1009, 1993],
    '202012': [1011, 1010, 1994],
    'Date': ['202004', '202006', '202010']
}
df = pd.DataFrame(data)
print("原始DataFrame:")
print(df)

2. 解决方案步骤

我们将通过以下几个关键步骤来实现数据的动态聚合:

2.1 重塑数据:从宽格式到长格式(melt)

原始DataFrame是宽格式的,日期列作为列名。为了方便与Date列进行比较和聚合,我们需要将其转换为长格式。pd.melt()函数可以将指定的列作为标识符变量,其余列作为值变量,并将列名转换为新的变量列。

# 标识符列:'Code', 'Date'
# 值列:所有日期列
tmp = df.melt(id_vars=['Code', 'Date'])
print("\n经过melt操作后的DataFrame (tmp):")
print(tmp.head())

tmp DataFrame现在包含 Code、Date、variable(原日期列名)和 value(对应数值)四列。

2.2 类型转换与条件判断

为了正确比较日期,我们需要确保Date列和variable列(它们现在都是字符串)的数据类型是可比较的。尽管它们是字符串,但如果格式一致(如'YYYYMM'),可以直接进行字符串比较。然后,我们将使用np.where()结合gt()(greater than)来判断每个variable日期是早于还是晚于其对应行的Date。

# 确保'Date'和'variable'列为字符串类型,以便进行比较
tmp = tmp.astype({'Date': str, 'variable': str})

# 创建新列'col',标记值是'Before'还是'After'指定日期
# 注意:这里'Before'包含等于指定日期的情况,'After'不包含
tmp['col'] = np.where(tmp['Date'].gt(tmp['variable']), 'Before', 'After')
print("\n添加'col'列后的DataFrame (tmp):")
print(tmp.head())

这里,tmp['Date'].gt(tmp['variable']) 比较的是字符串大小,对于'YYYYMM'格式的日期字符串,这等同于日期比较。如果Date晚于variable,则variable属于Before,否则属于After。

2.3 分组聚合(groupby和sum)

现在,我们可以根据Code和新创建的col列('Before'或'After')进行分组,并对value列求和。

# 按Code和col分组,并对value求和
grouped_sums = tmp.groupby(['Code', 'col'])['value'].sum()
print("\n分组求和后的Series (grouped_sums):")
print(grouped_sums.head())

结果是一个MultiIndex Series。

Artbreeder
Artbreeder

创建令人惊叹的插画和艺术

下载

2.4 重构结果(unstack)

为了将'Before'和'After'作为独立的列,我们需要使用unstack('col')。

# 将'col'的索引层转为列
unstacked_sums = grouped_sums.unstack('col')
print("\nunstack后的DataFrame (unstacked_sums):")
print(unstacked_sums.head())

此时,unstacked_sums DataFrame的索引是Code,列是Before和After。为了保持与原DataFrame的列顺序一致,可以进行列重排。

# 确保'Before'和'After'列的顺序
unstacked_sums = unstacked_sums[['Before', 'After']]
print("\n重排列顺序后的DataFrame (unstacked_sums):")
print(unstacked_sums.head())

2.5 合并回原DataFrame(merge)

最后一步是将计算出的Before和After总和合并回原始的df DataFrame。我们使用left_on='Code'和right_index=True,因为unstacked_sums的索引就是Code。

# 将计算结果合并回原始DataFrame
out = df.merge(unstacked_sums, left_on='Code', right_index=True, how='left')
print("\n最终结果DataFrame:")
print(out)

3. 完整代码示例

将上述所有步骤整合,完整的解决方案代码如下:

import pandas as pd
import numpy as np

# 1. 创建示例数据
data = {
    'Code': ['12345', '12346', '12347'],
    '202001': [1000, 999, 1983],
    '202002': [1001, 1000, 1984],
    '202003': [1002, 1001, 1985],
    '202004': [1003, 1002, 1986],
    '202005': [1004, 1003, 1987],
    '202006': [1005, 1003, 1988],
    '202007': [3006, 1005, 1989],
    '202008': [1007, 1006, 1990],
    '202009': [1008, 1007, 1991],
    '202010': [1009, 1008, 1992],
    '202011': [1010, 1009, 1993],
    '202012': [1011, 1010, 1994],
    'Date': ['202004', '202006', '202010']
}
df = pd.DataFrame(data)

# 2. 核心计算逻辑
tmp = (df.melt(id_vars=['Code', 'Date'])
       .astype({'Date': str, 'variable': str}) # 确保日期字符串可比较
       .assign(col=lambda d: np.where(d['Date'].gt(d['variable']), 'Before', 'After')) # 条件判断
       .groupby(['Code', 'col'])['value'].sum() # 分组求和
       .unstack('col')[['Before', 'After']] # 重构列并确保顺序
      )

# 3. 合并回原始DataFrame
out = df.merge(tmp, left_on='Code', right_index=True, how='left')

print(out)

4. 输出结果

运行上述代码,将得到如下输出:

    Code  202001  202002  202003  202004  202005  202006  202007  202008  202009  202010  202011  202012    Date  Before  After
0  12345    1000    1001    1002    1003    1004    1005    3006    1007    1008    1009    1010    1011  202004    3003  11063
1  12346     999    1000    1001    1002    1003    1003    1005    1006    1007    1008    1009    1010  202006    5005   7048
2  12347    1983    1984    1985    1986    1987    1988    1989    1990    1991    1992    1993    1994  202010   17883   5979

可以看到,Before和After两列已成功添加到原始DataFrame中,并且数值计算正确。

5. 注意事项

  • 日期格式一致性: 确保所有日期列名(如'202001')和Date列中的日期字符串格式一致。本示例中使用了'YYYYMM'格式,这使得字符串比较能够正确反映日期先后。如果日期格式复杂,建议先将它们转换为Pandas的datetime对象进行比较。
  • 现有列处理: 如果原始DataFrame中已经存在名为Before或After的列,您可能需要在执行merge操作之前将其drop掉,以避免列名冲突。
  • 性能考量: 对于非常大的DataFrame,melt操作可能会消耗较多内存。但在大多数情况下,这种链式操作是高效且Pandas推荐的。
  • “之前”的定义: 本例中,Before的定义是严格早于Date列的日期。如果需要包含Date列本身,则需要调整np.where中的比较逻辑(例如,使用d['Date'].ge(d['variable'])来定义After,或者调整Before的判断)。在示例代码中,tmp['Date'].gt(tmp['variable'])判断的是 Date > variable,即 variable 比 Date 早,所以 variable 属于 Before。这意味着 Before 包含了所有 variable 小于 Date 的值。

6. 总结

本教程展示了如何利用Pandas的melt、astype、assign(结合np.where)、groupby、unstack和merge等函数,以声明式和高效的方式解决根据行内特定日期动态聚合数据的问题。这种方法不仅代码简洁,而且在处理中大型数据集时表现良好,是进行复杂数据转换和分析的有力工具。掌握这种数据重塑和聚合的技巧,将极大地提升您在Pandas中的数据处理能力。

相关专题

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

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

51

2025.12.04

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

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

301

2023.10.31

php数据类型
php数据类型

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

222

2025.10.31

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

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

180

2023.12.04

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

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

277

2024.02.23

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

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

252

2025.06.11

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

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

121

2025.08.07

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

254

2023.08.03

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

36

2026.01.14

热门下载

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

精品课程

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

共58课时 | 3.6万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

ASP 教程
ASP 教程

共34课时 | 3.6万人学习

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

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