使用pandas.to_datetime时仅保留日期部分


201

pandas.to_datetime用来解析数据中的日期。默认情况下,熊猫代表日期,datetime64[ns]即使所有日期都是每天也是如此。我想知道是否存在一种优雅/巧妙的方法来将日期转换为datetime.date或,datetime64[D]以便当我将数据写入CSV时,日期不附加00:00:00。我知道我可以手动逐个元素地转换类型:

[dt.to_datetime().date() for dt in df.dates]

但这确实很慢,因为我有很多行,这有点违反了使用目的pandas.to_datetime。有没有一种方法可以一次转换dtype整个列?或者,是否pandas.to_datetime支持精度规范,以便在处理日常数据时可以省去时间部分?


2
我不知道一种好方法,但是df.dates.apply(lambda x: x.date()) 至少应该快一点。也看看github.com/pydata/pandas/issues/2583


1
我认为这两个问题是不同的。您引用的可能重复项旨在从datetime列中拆分日期部分和时间部分。这个问题是通过一次转换整个列来激发的。假设您有一个包含20列代表日期的数据框。您不想指定要写入csv的列,如另一个问题中所建议。

1
目前不支持此功能(@root指向可能的增强功能),当写入csv时这样做的目的是什么?
杰夫,

3
好吧,通常我们必须将数据写入csv文件,以供其他程序读取。多余的00:00:00通常会使处理起来更加困难,尤其是当我处理纯日常数据时。

Answers:


285

从版本开始,0.15.0现在可以轻松地通过.dt仅访问日期组件来完成此操作:

df['just_date'] = df['dates'].dt.date

上面的方法返回一个datetime.datedtype,如果您想要一个a,datetime64则可以normalize将时间分量设置为午夜,以便将所有值设置为00:00:00

df['normalised_date'] = df['dates'].dt.normalize()

这会使dtype保持不变,datetime64但显示屏仅显示该date值。


33

简单的解决方案:

df['date_only'] = df['date_time_column'].dt.date

只是警告,这会将类型更改为对象。因此,您需要astype('datetime64')保持一致性。
凌晨

25

虽然我赞成EdChum的答案,这是对OP提出的问题的最直接答案,但它并不能真正解决性能问题(它仍然依赖于python datetime对象,因此对它们的任何操作都不会被矢量化-即,它会很慢)。

性能更好的替代方法是使用df['dates'].dt.floor('d')。严格来说,它不会“仅保留日期部分”,因为它只是将时间设置为00:00:00。但是它确实可以按OP的要求运行,例如:

  • 打印到屏幕
  • 保存到csv
  • 使用列来 groupby

...并且效率更高,因为该操作已矢量化。

编辑:其实,在OP的宁愿答案很可能是“最近的版本pandas没有时间写为csv如果是00:00:00对所有的意见”。


不幸的是to_json仍然写完整00:00:00
IanS

@IanS是什么意思date_format='iso'?默认情况下,它仅输出从纪元开始的秒数。
彼得罗·巴蒂斯顿

是的,这就是我的意思。
IanS

这比dt.normalize()系列上要快几百个元素。
C8H10N4O2

15

熊猫DatetimeIndexSeries有一种方法normalize可以完全满足您的需求。

您可以在此答案中了解更多信息。

可以用作 ser.dt.normalize()


15

熊猫v0.13 +:to_csvdate_format参数一起使用

尽可能避免将您的datetime64[ns]系列转换为objectdtype系列的datetime.date对象。后者通常使用构造pd.Series.dt.date,存储为指针数组,相对于基于NumPy的纯序列而言效率低下。

由于在写入CSV时您关注的是格式,因此只需使用date_format参数to_csv。例如:

df.to_csv(filename, date_format='%Y-%m-%d')

有关格式设置约定,请参见Python的strftime指令


8

这是提取日期的简单方法:

import pandas as pd

d='2015-01-08 22:44:09' 
date=pd.to_datetime(d).date()
print(date)

OP已经在他们的问题中使用了.date()方法,因此该解决方案无法回答他们的问题,但是我发现查看使用date()方法作为参考的简单示例确实有用。
Nic Sc​​ozzaro

5

转换为datetime64[D]

df.dates.values.astype('M8[D]')

尽管将其重新分配给DataFrame col将其恢复为[ns]。

如果您想要实际的datetime.date

dt = pd.DatetimeIndex(df.dates)
dates = np.array([datetime.date(*date_tuple) for date_tuple in zip(dt.year, dt.month, dt.day)])

3
如果使用astype('M8 [D]'),它将丢失的值转换为原始日期1970-1-1。如今最好只使用pandas.to_datetime()。
Stewbaca

1
请注意通常将datetime模块包含为的任何人dt,此答案片段将覆盖该模块!@ Dale-Jung,也许可以将行更改为类似dt_index的格式
yeliabsalohcin

我还发现了一个问题,下次我下次尝试通过该df.loc[date]方法添加新行时,索引将还原为时间戳,这意味着后续比较不再起作用
yeliabsalohcin

3

如果有人看到此旧帖子,请给出一个最新的答案。

转换为日期时间时添加“ utc = False”将删除时区部分,仅将日期保留为datetime64 [ns]数据类型。

pd.to_datetime(df['Date'], utc=False)

您将能够将其保存在excel中,而不会出现错误“ ValueError:Excel不支持带时区的日期时间。在写入Excel之前,请确保日期时间不知道时区。”

在此处输入图片说明


在列上应用任何聚合函数后,由于某种原因,此操作将失败。
RaphX

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.