0

0

使用 Pandas 基于日期范围条件填充 DataFrame

DDD

DDD

发布时间:2025-10-18 13:32:01

|

841人浏览过

|

来源于php中文网

原创

使用 Pandas 基于日期范围条件填充 DataFrame

本教程详细介绍了如何使用 pandas 在两个 dataframe 之间进行条件性数据填充。通过将一个 dataframe 的数据根据另一个 dataframe 定义的日期范围进行筛选和合并,最终生成一个符合特定日期范围要求的新 dataframe。核心方法包括日期类型转换、数据重塑(`melt`)、基于日期索引的近似合并(`merge_asof`)以及条件性数据筛选和透视(`pivot`),旨在高效处理复杂的时序数据关联任务。

在数据分析和处理中,我们经常会遇到需要根据特定条件从一个数据集中提取或填充另一个数据集的场景。特别是当条件涉及日期范围时,操作会变得更加复杂。本教程将展示如何利用 Pandas 库的强大功能,实现根据一个 DataFrame 定义的日期范围,从另一个 DataFrame 中有条件地填充数据。

场景描述

假设我们有两个 DataFrame:

  1. df1:包含公司及其对应的有效日期范围(start date 和 end date)。
  2. df2:包含按日期和公司分组的实际数据。

我们的目标是创建一个新的 DataFrame (df3),其中 df2 中的数据仅在 df1 定义的相应公司的日期范围内才有效。超出范围的数据应显示为 NaN。

示例输入数据:

import pandas as pd

# df1: 定义日期范围
data1 = {'company': {0: 'a', 1: 'b', 2: 'c', 3: 'd'},
         'start date': {0: '2023-01-02', 1: '2023-01-05', 2: '2023-01-04', 3: '2023-01-03'},
         'end date': {0: '2023-01-06', 1: '2023-01-12', 2: '2023-01-13', 3: '2023-01-10'}}
df1 = pd.DataFrame(data1)

# df2: 原始数据
data2 = {'DATE': {0: '2023-01-02', 1: '2023-01-03', 2: '2023-01-04', 3: '2023-01-05',
                  4: '2023-01-06', 5: '2023-01-09', 6: '2023-01-10', 7: '2023-01-11',
                  8: '2023-01-12', 9: '2023-01-13'},
         'a': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10},
         'b': {0: 10, 1: 11, 2: 12, 3: 13, 4: 14, 5: 15, 6: 16, 7: 17, 8: 18, 9: 19},
         'c': {0: 30, 1: 31, 2: 32, 3: 33, 4: 34, 5: 35, 6: 36, 7: 37, 8: 38, 9: 39},
         'd': {0: 40, 1: 41, 2: 42, 3: 43, 4: 44, 5: 45, 6: 46, 7: 47, 8: 48, 9: 49}}
df2 = pd.DataFrame(data2)

print("df1:")
print(df1)
print("\ndf2:")
print(df2)

步骤一:日期列类型转换

在进行任何日期相关的操作之前,确保所有日期列都被正确识别为 datetime 类型至关重要。这可以防止潜在的类型不匹配错误,并允许使用 Pandas 强大的日期时间功能。

df1['start date'] = pd.to_datetime(df1['start date'])
df1['end date'] = pd.to_datetime(df1['end date'])
df2['DATE'] = pd.to_datetime(df2['DATE'])

print("\ndf1 (after type conversion):")
print(df1)
print("\ndf2 (after type conversion):")
print(df2)

步骤二:数据重塑、合并与条件筛选

这一步是解决方案的核心,它涉及将数据从宽格式转换为长格式,执行近似合并,然后应用日期范围条件进行筛选。

  1. 数据重塑 (melt): df2 当前是宽格式,每个公司有一列。为了能按公司和日期与 df1 进行合并,我们需要将其转换为长格式,即每行包含 DATE、company 和 value。

    df2_melted = df2.melt('DATE', var_name='company', value_name='value')
    # 打印部分结果以理解 melt 的作用
    # print("\ndf2_melted (partial):")
    # print(df2_melted.head())
  2. 数据排序: merge_asof 要求其左侧和右侧的 DataFrame 都必须按合并键进行排序。对于我们的场景,df2_melted 需要按 DATE 排序,df1 需要按 start date 排序。

    Cutout.Pro抠图
    Cutout.Pro抠图

    AI批量抠图去背景

    下载
    df2_melted_sorted = df2_melted.sort_values('DATE')
    df1_sorted = df1.sort_values('start date')
  3. 近似合并 (merge_asof): merge_asof 是一个强大的工具,用于执行“as of”合并,即在左 DataFrame 的键值大于或等于右 DataFrame 的键值时,合并最近的行。在这里,我们希望将 df2_melted 中的每个 DATE 与 df1 中对应的 company 的 start date 进行匹配。

    • left_on='DATE':df2_melted 的合并键。
    • right_on='start date':df1 的合并键。
    • by='company':确保仅在相同的 company 下进行合并。
    tmp = pd.merge_asof(df2_melted_sorted,
                        df1_sorted,
                        by='company',
                        left_on='DATE',
                        right_on='start date')
    # print("\ntmp (after merge_asof, partial):")
    # print(tmp.head(10))

    此时,tmp DataFrame 包含了 df2 的原始值,以及从 df1 合并过来的 start date 和 end date。重要的是,merge_asof 确保了 DATE >= start date。

  4. 条件性数据筛选 (where): merge_asof 已经确保了 DATE 不早于 start date。现在,我们还需要确保 DATE 不晚于 end date。我们可以使用 DataFrame.where() 方法,它会根据条件保留值,不满足条件的则替换为 NaN。

    tmp['value'] = tmp['value'].where(tmp['DATE'].le(tmp['end date']))
    # print("\ntmp (after conditional filtering, partial):")
    # print(tmp.head(10))
  5. 数据透视 (pivot): 最后,我们将处理后的 tmp DataFrame 从长格式重新透视回我们期望的宽格式,其中 DATE 作为索引,company 作为列,value 作为数据。

    df3 = tmp.pivot(index='DATE', columns='company', values='value')\
             .rename_axis('', axis=1)\
             .reset_index()

完整代码示例

将上述所有步骤整合,得到完整的解决方案:

import pandas as pd

# 1. 准备数据
data1 = {'company': {0: 'a', 1: 'b', 2: 'c', 3: 'd'},
         'start date': {0: '2023-01-02', 1: '2023-01-05', 2: '2023-01-04', 3: '2023-01-03'},
         'end date': {0: '2023-01-06', 1: '2023-01-12', 2: '2023-01-13', 3: '2023-01-10'}}
df1 = pd.DataFrame(data1)

data2 = {'DATE': {0: '2023-01-02', 1: '2023-01-03', 2: '2023-01-04', 3: '2023-01-05',
                  4: '2023-01-06', 5: '2023-01-09', 6: '2023-01-10', 7: '2023-01-11',
                  8: '2023-01-12', 9: '2023-01-13'},
         'a': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10},
         'b': {0: 10, 1: 11, 2: 12, 3: 13, 4: 14, 5: 15, 6: 16, 7: 17, 8: 18, 9: 19},
         'c': {0: 30, 1: 31, 2: 32, 3: 33, 4: 34, 5: 35, 6: 36, 7: 37, 8: 38, 9: 39},
         'd': {0: 40, 1: 41, 2: 42, 3: 43, 4: 44, 5: 45, 6: 46, 7: 47, 8: 48, 9: 49}}
df2 = pd.DataFrame(data2)

# 2. 日期列类型转换
df1['start date'] = pd.to_datetime(df1['start date'])
df1['end date'] = pd.to_datetime(df1['end date'])
df2['DATE'] = pd.to_datetime(df2['DATE'])

# 3. 数据重塑、合并与条件筛选
# 将 df2 从宽格式转换为长格式,便于按公司合并
df2_melted = df2.melt('DATE', var_name='company', value_name='value')

# 对两个 DataFrame 进行排序,以满足 merge_asof 的要求
df2_melted_sorted = df2_melted.sort_values('DATE')
df1_sorted = df1.sort_values('start date')

# 使用 merge_asof 进行近似合并,按公司和日期进行匹配
# left_on='DATE' 和 right_on='start date' 确保 DATE >= start date
tmp = pd.merge_asof(df2_melted_sorted,
                    df1_sorted,
                    by='company',
                    left_on='DATE',
                    right_on='start date')

# 应用第二个日期范围条件:确保 DATE <= end date
# 不满足条件的 'value' 将被设置为 NaN
tmp['value'] = tmp['value'].where(tmp['DATE'].le(tmp['end date']))

# 将结果从长格式透视回宽格式
df3 = tmp.pivot(index='DATE', columns='company', values='value')\
         .rename_axis('', axis=1)\
         .reset_index()

print("\nDesired Output (df3):")
print(df3)

注意事项与总结

  1. 日期类型的重要性: 始终确保日期列为 datetime 类型。这是 Pandas 进行日期比较和 merge_asof 操作的基础。
  2. melt 的作用: melt 函数将宽格式数据转换为长格式,这在进行多条件(例如,按公司和日期)合并时非常有用,因为它将公司名称从列名转换为可用于合并的实际数据。
  3. merge_asof 的特性: merge_asof 执行的是“as of”合并,即对于左侧 DataFrame 中的每一行,它会查找右侧 DataFrame 中最近的、不大于左侧键值的行。在本例中,我们利用 left_on='DATE' 和 right_on='start date' 来确保合并的行满足 DATE >= start date 的条件。
  4. 排序要求: merge_asof 要求两个待合并的 DataFrame 都必须根据合并键进行排序。
  5. where 的应用: DataFrame.where() 方法提供了一种简洁高效的方式来根据条件替换 DataFrame 中的值,非常适合我们根据 end date 进行二次筛选的需求。
  6. pivot 的逆操作: pivot 是 melt 的逆操作,它将长格式数据重新转换为宽格式,生成最终所需的输出结构。

通过以上步骤,我们成功地利用 Pandas 实现了根据日期范围条件从一个 DataFrame 填充另一个 DataFrame 的复杂数据处理任务。这种方法灵活且高效,适用于各种需要基于时间范围进行数据关联和筛选的场景。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

71

2025.12.04

Python 数据清洗与预处理实战
Python 数据清洗与预处理实战

本专题系统讲解 Python 在数据清洗与预处理中的核心技术,包括使用 Pandas 进行缺失值处理、异常值检测、数据格式化、特征工程与数据转换,结合 NumPy 高效处理大规模数据。通过实战案例,帮助学习者掌握 如何处理混乱、不完整数据,为后续数据分析与机器学习模型训练打下坚实基础。

1

2026.01.31

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

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

301

2025.07.15

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

52

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

40

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

50

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

11

2026.01.31

漫画防走失登陆入口大全
漫画防走失登陆入口大全

2026最新漫画防走失登录入口合集,汇总多个稳定可用网址,助你畅享高清无广告漫画阅读体验。阅读专题下面的文章了解更多详细内容。

13

2026.01.31

php多线程怎么实现
php多线程怎么实现

PHP本身不支持原生多线程,但可通过扩展如pthreads、Swoole或结合多进程、协程等方式实现并发处理。阅读专题下面的文章了解更多详细内容。

1

2026.01.31

热门下载

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

精品课程

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

共58课时 | 4.4万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.0万人学习

ASP 教程
ASP 教程

共34课时 | 4.3万人学习

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

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