Pandas中合并日期与时间列以避免转换错误

碧海醫心
发布: 2025-11-18 13:14:20
原创
360人浏览过

pandas中合并日期与时间列以避免转换错误

在Pandas中将单独的日期和时间字符串列转换为`datetime`类型时,如果时间列不包含日期信息,`pd.to_datetime`默认会填充当前系统日期,导致日期部分被意外更改。本文将详细介绍如何通过字符串拼接或更推荐的日期时间与时间差组合方式,正确地将分散的日期和时间信息合并为一个完整的`datetime`对象,确保数据转换的准确性。

理解日期时间转换中的常见陷阱

在使用Pandas处理时间序列数据时,经常会遇到日期和时间信息存储在不同的列中的情况。例如,一个DataFrame可能包含一个order_date列(仅日期)和一个order_time列(仅时间)。当尝试将这些列转换为标准的datetime对象时,如果不采取正确的策略,可能会导致数据不一致。

考虑以下初始DataFrame:

import pandas as pd

data = {
    'order_details_id': [1, 2, 3, 4, 5],
    'order_id': [1, 2, 2, 2, 2],
    'order_date': ['1/1/23', '1/1/23', '1/1/23', '1/1/23', '1/1/23'],
    'order_time': ['11:38:36 AM', '11:57:40 AM', '11:57:40 AM', '11:57:40 AM', '11:57:40 AM'],
    'item_id': [109.0, 108.0, 124.0, 117.0, 129.0]
}
df = pd.DataFrame(data)
print("原始DataFrame:")
print(df)
print("\n原始数据类型:")
print(df.dtypes)
登录后复制

输出:

原始DataFrame:
   order_details_id  order_id order_date   order_time  item_id
0                 1         1     1/1/23  11:38:36 AM    109.0
1                 2         2     1/1/23  11:57:40 AM    108.0
2                 3         2     1/1/23  11:57:40 AM    124.0
3                 4         2     1/1/23  11:57:40 AM    117.0
4                 5         2     1/1/23  11:57:40 AM    129.0

原始数据类型:
order_details_id      int64
order_id              int64
order_date           object
order_time           object
item_id             float64
dtype: object
登录后复制

如果尝试单独转换order_date和order_time列,会发现order_time列在转换为datetime类型后,其日期部分被意外地更改为当前系统日期。

# 错误示范:单独转换时间列
df_copy = df.copy()
df_copy['order_date'] = pd.to_datetime(df_copy['order_date'])
df_copy['order_time'] = pd.to_datetime(df_copy['order_time'])
print("\n错误转换后的DataFrame (order_time日期被改变):")
print(df_copy)
登录后复制

输出(order_time的日期部分会显示为你运行代码时的日期,例如2023-12-29):

错误转换后的DataFrame (order_time日期被改变):
   order_details_id  order_id  order_date          order_time  item_id
0                 1         1  2023-01-01   2023-12-29 11:38:36    109.0
1                 2         2  2023-01-01   2023-12-29 11:57:40    108.0
2                 3         2  2023-01-01   2023-12-29 11:57:40    124.0
3                 4         2  2023-01-01   2023-12-29 11:57:40    117.0
4                 5         2  2023-01-01   2023-12-29 11:57:40    129.0
登录后复制

原因分析:order_time列的字符串(如"11:38:36 AM")仅包含时间信息,不包含日期。当pd.to_datetime函数在没有明确日期信息的情况下处理此类字符串时,它会默认使用当前系统日期来填充缺失的日期部分。这通常不是我们期望的行为,因为我们希望保留order_date列提供的原始日期。

正确合并日期与时间的方法

为了避免上述问题,我们应该在将数据转换为datetime类型之前,将日期和时间信息合并在一起。以下是几种推荐的方法。

方法一:字符串拼接后进行转换

最直观的方法是将order_date和order_time两列的字符串内容拼接成一个新的字符串列,然后对这个新列应用pd.to_datetime。

df_method1 = df.copy()
df_method1['order_datetime'] = pd.to_datetime(df_method1['order_date'].str.cat(df_method1['order_time'], sep=' '))
print("\n方法一:字符串拼接后转换:")
print(df_method1)
print("\n方法一:数据类型检查:")
print(df_method1.dtypes)
登录后复制

输出:

方法一:字符串拼接后转换:
   order_details_id  order_id order_date   order_time  item_id      order_datetime
0                 1         1     1/1/23  11:38:36 AM    109.0 2023-01-01 11:38:36
1                 2         2     1/1/23  11:57:40 AM    108.0 2023-01-01 11:57:40
2                 3         2     1/1/23  11:57:40 AM    124.0 2023-01-01 11:57:40
3                 4         2     1/1/23  11:57:40 AM    117.0 2023-01-01 11:57:40
4                 5         2     1/1/23  11:57:40 AM    129.0 2023-01-01 11:57:40

方法一:数据类型检查:
order_details_id             int64
order_id                     int64
order_date                  object
order_time                  object
item_id                    float64
order_datetime      datetime64[ns]
dtype: object
登录后复制

这种方法简单易懂,通过在日期和时间之间添加一个空格进行拼接,pd.to_datetime能够识别并正确解析。

美间AI
美间AI

美间AI:让设计更简单

美间AI 45
查看详情 美间AI

方法二:日期时间与时间差组合(推荐)

这种方法更为健壮和推荐,它将order_date转换为datetime对象,将order_time转换为timedelta(时间差)对象,然后将两者相加。这种方式避免了字符串操作可能带来的格式问题,并且在语义上更清晰。

df_method2 = df.copy()
# 将order_date转换为datetime类型
df_method2['order_date_dt'] = pd.to_datetime(df_method2['order_date'])
# 将order_time转换为timedelta类型
df_method2['order_time_td'] = pd.to_timedelta(df_method2['order_time'])

# 将datetime和timedelta相加
df_method2['order_datetime'] = df_method2['order_date_dt'] + df_method2['order_time_td']

# 可以选择删除中间列
df_method2 = df_method2.drop(columns=['order_date_dt', 'order_time_td'])

print("\n方法二:日期时间与时间差组合:")
print(df_method2)
print("\n方法二:数据类型检查:")
print(df_method2.dtypes)
登录后复制

为了更简洁,可以直接在赋值时使用pop()方法,这样可以同时删除原始列:

df_method2_pop = df.copy()
df_method2_pop['order_datetime'] = pd.to_datetime(df_method2_pop.pop('order_date')) + pd.to_timedelta(df_method2_pop.pop('order_time'))
print("\n方法二(使用pop()):日期时间与时间差组合:")
print(df_method2_pop)
print("\n方法二(使用pop()):数据类型检查:")
print(df_method2_pop.dtypes)
登录后复制

输出与方法一类似,但数据处理过程更为类型安全:

方法二:日期时间与时间差组合:
   order_details_id  order_id  item_id      order_datetime
0                 1         1    109.0 2023-01-01 11:38:36
1                 2         2    108.0 2023-01-01 11:57:40
2                 3         2    124.0 2023-01-01 11:57:40
3                 4         2    117.0 2023-01-01 11:57:40
4                 5         2    129.0 2023-01-01 11:57:40

方法二:数据类型检查:
order_details_id             int64
order_id                     int64
item_id                    float64
order_datetime      datetime64[ns]
dtype: object
登录后复制

这种方法不仅解决了日期被更改的问题,还提供了更清晰的数据类型转换路径:日期字符串转换为日期时间,时间字符串转换为时间差,然后相加得到完整的日期时间。

方法三:优化数据读取(如果可能)

如果数据源允许,最理想的情况是在数据导入时就将日期和时间作为一个整体字符串来读取。这样可以简化后续的转换步骤。

假设原始数据已经被预处理成如下格式:

data_combined = {
    'order_details_id': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
    'order_id': {0: 1, 1: 2, 2: 2, 3: 2, 4: 2},
    'order_date_time': {0: '1/1/23 11:38:36 AM',
                        1: '1/1/23 11:57:40 AM',
                        2: '1/1/23 11:57:40 AM',
                        3: '1/1/23 11:57:40 AM',
                        4: '1/1/23 11:57:40 AM'},
    'item_id': {0: 109.0, 1: 108.0, 2: 124.0, 3: 117.0, 4: 129.0}
}
df_combined = pd.DataFrame(data_combined)
print("\n方法三:初始数据已合并日期时间:")
print(df_combined)

df_combined['order_dt'] = pd.to_datetime(df_combined['order_date_time'])
print("\n方法三:直接转换合并列:")
print(df_combined)
print("\n方法三:数据类型检查:")
print(df_combined.dtypes)
登录后复制

输出:

方法三:初始数据已合并日期时间:
   order_details_id  order_id     order_date_time  item_id
0                 1         1  1/1/23 11:38:36 AM    109.0
1                 2         2  1/1/23 11:57:40 AM    108.0
2                 3         2  1/1/23 11:57:40 AM    124.0
3                 4         2  1/1/23 11:57:40 AM    117.0
4                 5         2  1/1/23 11:57:40 AM    129.0

方法三:直接转换合并列:
   order_details_id  order_id     order_date_time  item_id            order_dt
0                 1         1  1/1/23 11:38:36 AM    109.0 2023-01-01 11:38:36
1                 2         2  1/1/23 11:57:40 AM    108.0 2023-01-01 11:57:40
2                 3         2  1/1/23 11:57:40 AM    124.0 2023-01-01 11:57:40
3                 4         2  1/1/23 11:57:40 AM    117.0 2023-01-01 11:57:40
4                 5         2  1/1/23 11:57:40 AM    129.0 2023-01-01 11:57:40

方法三:数据类型检查:
order_details_id             int64
order_id                     int64
order_date_time             object
item_id                    float64
order_dt            datetime64[ns]
dtype: object
登录后复制

这种方法最为简洁,因为pd.to_datetime可以直接处理包含完整日期和时间信息的字符串。

注意事项

  • 明确数据来源:在进行日期时间转换前,务必了解原始数据中日期和时间的存储方式。是单独存储,还是已经合并?
  • 格式参数:如果日期时间字符串的格式不标准或不一致,可以使用pd.to_datetime的format参数明确指定解析格式,例如 pd.to_datetime(series, format='%Y-%m-%d %H:%M:%S')。这有助于提高解析效率和准确性,尤其是在处理大量数据时。
  • 错误处理:pd.to_datetime的errors参数可以控制如何处理解析错误。'coerce'会将无法解析的值转换为NaT(Not a Time),而'raise'(默认)则会抛出错误。
  • 性能考量:对于大型数据集,字符串拼接(方法一)可能比timedelta方法(方法二)略慢,因为涉及到更多的字符串操作。方法二通过数值运算(datetime + timedelta)通常效率更高。

总结

在Pandas中处理分散的日期和时间列时,直接将不含日期信息的时间字符串转换为datetime类型会导致日期部分被当前系统日期覆盖。为了确保数据转换的准确性,推荐以下策略:

  1. 将日期和时间字符串拼接成一个完整的日期时间字符串,然后使用pd.to_datetime进行转换。
  2. 将日期列转换为datetime对象,将时间列转换为timedelta对象,然后将两者相加得到最终的datetime对象。 这种方法在类型安全性和性能方面通常更优。
  3. 如果数据源允许,在数据导入阶段就将日期和时间合并为一个字段,后续直接转换。

通过采用这些方法,您可以有效地管理和转换时间序列数据,避免常见的日期时间处理陷阱,确保数据分析的准确性和可靠性。

以上就是Pandas中合并日期与时间列以避免转换错误的详细内容,更多请关注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号