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

碧海醫心
发布: 2025-08-14 20:50:24
原创
1020人浏览过

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。

硅基智能
硅基智能

基于Web3.0的元宇宙,去中心化的互联网,高质量、沉浸式元宇宙直播平台,用数字化重新定义直播

硅基智能 62
查看详情 硅基智能

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中的数据处理能力。

以上就是Pandas DataFrame中基于指定日期进行数据聚合与分析的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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