
在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能够识别并正确解析。
这种方法更为健壮和推荐,它将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可以直接处理包含完整日期和时间信息的字符串。
在Pandas中处理分散的日期和时间列时,直接将不含日期信息的时间字符串转换为datetime类型会导致日期部分被当前系统日期覆盖。为了确保数据转换的准确性,推荐以下策略:
通过采用这些方法,您可以有效地管理和转换时间序列数据,避免常见的日期时间处理陷阱,确保数据分析的准确性和可靠性。
以上就是Pandas中合并日期与时间列以避免转换错误的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号