使用 astype
函数将 pandas 数据帧列从 object
转换为 datetime
时,行为会有所不同,具体取决于字符串是否有时间组件与否。转换列的正确方法是什么?
df = pd.DataFrame({'Date': ['12/07/2013 21:50:00','13/07/2013 00:30:00','15/07/2013','11/07/2013']})
df['Date'] = pd.to_datetime(df['Date'], format="%d/%m/%Y %H:%M:%S", exact=False, dayfirst=True, errors='ignore')
输出:
Date
0 12/07/2013 21:50:00
1 13/07/2013 00:30:00
2 15/07/2013
3 11/07/2013
但数据类型仍然是object
。做的时候:
df['Date'] = df['Date'].astype('datetime64')
它变为datetime
dtype,但第 0 行和第 3 行的日期和月份未正确解析。
Date
0 2013-12-07 21:50:00
1 2013-07-13 00:30:00
2 2013-07-15 00:00:00
3 2013-11-07 00:00:00
预期结果是:
Date
0 2013-07-12 21:50:00
1 2013-07-13 00:30:00
2 2013-07-15 00:00:00
3 2013-07-11 00:00:00
最佳答案
如果我们看一下source code ,如果您传递 format=
和 dayfirst=
参数,则 dayfirst=
将永远不会被读取,因为传递 format=
调用不使用 dayfirst=
进行转换的 C 函数 (np_datetime_strings.c)。另一方面,如果您仅传递 dayfirst=
,它将用于首先猜测格式,然后依靠 dateutil.parser.parse
进行转换。因此,仅使用其中之一。
在大多数情况下,
df['Date'] = pd.to_datetime(df['Date'])
完成工作。
在OP的具体示例中,传递dayfirst=True
即可完成这项工作。
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)
也就是说,传递 format=
会使转换运行速度提高约 25 倍(有关更多信息,请参阅 this post),因此,如果您的帧大于 10k 行,那么最好传递格式=
。现在,由于格式是混合的,一种方法是分两步执行转换(errors='coerce'
参数将很有用)
- 使用时间组件转换日期时间
- 填写使用不同格式转换的系列的 NaT 值(“强制”行)。
df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y %H:%M:%S', errors='coerce')
df['Date'] = df['Date'].fillna(pd.to_datetime(df['Date'], format='%d/%m/%Y', errors='coerce'))
此方法(执行或更多转换)可用于转换具有“奇怪”格式的日期时间的任何列。
从 pandas 2.0 开始,format=
接受 'mixed'
,即 pd.to_datetime(dates, format='mixed')
但这很容易出错,因此最好使用 dayfirst=True
或两步 format=
(如上所述)。
关于python - 将混合格式字符串列转换为日期时间 Dtype,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56614558/