【问题标题】:Keep only date part when using pandas.to_datetime使用 pandas.to_datetime 时只保留日期部分
【发布时间】:2013-04-17 02:51:27
【问题描述】:

我使用pandas.to_datetime 解析数据中的日期。 Pandas 默认使用datetime64[ns] 表示日期,即使这些日期都是每天的。 我想知道是否有一种优雅/聪明的方法可以将日期转换为datetime.datedatetime64[D],这样,当我将数据写入 CSV 时,日期不会附加00:00:00。我知道我可以逐个元素地手动转换类型:

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

但这真的很慢,因为我有很多行,这有点违背使用pandas.to_datetime 的目的。有没有办法一次转换整列的dtype?或者,pandas.to_datetime 是否支持精度规范,以便我可以在处理日常数据时摆脱时间部分?

【问题讨论】:

    标签: python pandas csv datetime series


    【解决方案1】:

    0.15.0 版本开始,现在可以使用.dt 轻松访问日期组件:

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

    上面返回一个datetime.date dtype,如果你想有一个datetime64,那么你可以把时间组件normalize 设置为午夜,所以它将所有值设置为00:00:00

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

    这会将dtype 保持为datetime64,但显示屏只显示date 值。

    【讨论】:

    • 这是最合适的答案
    • @edChum 以 MM-DD-YYYY 格式格式化日期?
    • 只能使用带有 datetimelike 值的 .dt 访问器
    【解决方案2】:

    简单的解决方案:

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

    【讨论】:

    • 只是一个警告,这会将类型更改为对象。所以你需要 astype('datetime64') 来保持一致性。
    【解决方案3】:

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

    A better performing alternative 是使用df['dates'].dt.floor('d')。严格来说,它不是“只保留日期部分”,因为它只是将时间设置为00:00:00。但它确实可以按照 OP 的要求工作,例如:

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

    ...而且效率更高,因为操作是矢量化的。

    编辑: 事实上,OP 更喜欢的答案可能是“pandas 的最新版本如果是 @987654327 则将时间写入 csv @ 表示所有观察结果”。

    【讨论】:

    • 不幸的是to_json 仍然写完整的00:00:00
    • @IanS 是指使用date_format='iso' 时的意思吗?!默认情况下,它只输出自纪元以来的秒数。
    • 是的,我就是这个意思。
    • 这比 dt.normalize() 在超过几百个元素的系列上更快。
    • 在大于 100 万行的 df 上,这比我发现的任何其他选项都快得多,除了 normalize 只是稍微慢一点。此外,保持日期 pandas-native 意味着它可以保存到 hdf 存储(datetime.date 列不能从 pandas 1.1.4 开始)。
    【解决方案4】:

    Pandas v0.13+:使用 to_csvdate_format 参数

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

    由于您关心的是写入 CSV 时的格式,因此只需使用 to_csvdate_format 参数即可。例如:

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

    有关格式约定,请参阅Python's strftime directives

    【讨论】:

      【解决方案5】:

      Pandas DatetimeIndexSeries 有一个名为 normalize 的方法,可以完全满足您的需求。

      您可以在this answer 阅读更多相关信息。

      可以用作ser.dt.normalize()

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

        • OP 已经在他们的问题中使用 .date() 方法,所以这个解决方案没有回答他们的问题,但我确实发现看到一个使用 date() 的简单示例很有用方法仅供参考。
        • 当用作日期解析器的 lambda 函数时,这似乎不起作用,即 date_parser=lambda col: pd.to_datetime(col, format="%y%m%d").date ()
        【解决方案7】:

        如果有人看到这篇旧帖子,请提供更新的答案。

        在转换为 datetime 时添加“utc=False”将删除时区组件并仅保留 datetime64[ns] 数据类型中的日期。

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

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

        【讨论】:

        • 在您对列应用任何聚合函数后,由于某种原因,这会失败。
        • @Katekarin 如果您尝试查看 df['Date'].values 它仍然会包含时间组件。
        【解决方案8】:

        转换为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)])
        

        【讨论】:

        • 如果您使用 astype('M8[D]') 它将缺失值转换为原始日期 1970-1-1。现在最好只使用 pandas.to_datetime() 。
        • 请注意任何经常将日期时间模块包含为dt 的人,此答案片段将覆盖该模块! @Dale-Jung,也许可以把这条线改成 dt_index
        • 我还发现了一个问题,即下次我尝试通过 df.loc[date] 方法添加新行时,索引会恢复为时间戳,这意味着后续比较不再有效
        【解决方案9】:

        我希望能够更改数据框中一组列的类型,然后删除保持一天的时间。 round(), floor(), ceil()所有工作

        df[date_columns] = df[date_columns].apply(pd.to_datetime)
        df[date_columns] = df[date_columns].apply(lambda t: t.dt.floor('d'))
        

        【讨论】:

          【解决方案10】:

          df['Column'] = df['Column'].dt.strftime('%m/%d/%Y')

          这将为您提供所需格式的日期和 NO TIME。您可以根据需要更改格式'%m/%d/%Y',它将将该列的数据类型更改为'object'


          如果您只想要日期而不想要YYYY-MM-DD 格式的时间,请使用:

          df['Column'] = pd.to_datetime(df['Column']).dt.date
          

          数据类型将为'object'


          对于'datetime64' 数据类型,使用:

          df['Column'] = pd.to_datetime(df['Column']).dt.normalize()
          

          【讨论】:

            【解决方案11】:

            在 >1000000 行的表上,我发现它们都很快,floor 稍微快一点:

            df['mydate'] = df.index.floor('d')
            

            df['mydate'] = df.index.normalize()
            

            如果您的索引有时区,而您不希望结果中出现这些时区,请执行以下操作:

            df['mydate'] = df.index.tz_localize(None).floor('d')
            

            df.index.date 慢很多倍; to_datetime() 更糟。两者都有进一步的缺点,即结果无法保存到 hdf 存储,因为它不支持类型 datetime.date。

            请注意,我在这里使用索引作为日期源;如果您的来源是另一列,则需要添加.dt,例如df.mycol.dt.floor('d')

            【讨论】:

              【解决方案12】:

              这对我来说适用于 UTC 时间戳 (2020-08-19T09:12:57.945888)

              for di, i in enumerate(df['YourColumnName']):
                  df['YourColumnName'][di] = pd.Timestamp(i)
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2019-01-02
                • 1970-01-01
                • 2013-05-16
                相关资源
                最近更新 更多