【问题标题】:Prevent Pandas to_json() from adding time component to date object防止 Pandas to_json() 将时间组件添加到日期对象
【发布时间】:2018-06-30 09:00:56
【问题描述】:

我有一个包含一些日期对象的数据框。我需要转换为 json 以在 JavaScript 中使用,这需要 YYYY-MM-DD,但 to_json() 不断添加时间组件。我已经看到了许多首先转换为字符串的答案,但这是大约 15 个查询的循环的一部分,每个查询都有很多列(为 SO 问题简化了它),我不想将每个列转换硬编码为有很多。

import pandas as pd
from datetime import date
df = pd.DataFrame(data=[[date(year=2018, month=1, day=1)]])    
print df.to_json(orient='records', date_format='iso', date_unit='s')

输出:

[{"0":"2018-01-01T00:00:00Z"}]

期望的输出:

[{"0":"2018-01-01"}]

【问题讨论】:

  • 我认为最好的办法是在将 df 转换为 json 之前格式化日期时间。

标签: python python-2.7 pandas date


【解决方案1】:

Pandas 目前没有该功能。有一个关于此的未解决问题,您应该订阅该问题,以防在将来的版本中添加更多date_format 参数选项(这似乎是一个合理的功能请求):

No way with to_json to write only date out of datetime #16492

在转储 json 之前手动将相关列转换为字符串可能是最好的选择。

【讨论】:

    【解决方案2】:

    您可以像这样使用strftime('%Y-%m-%d') 格式:

    df = pd.DataFrame(data=[[date(year=2018, month=1, day=1).strftime('%Y-%m-
        %d')]]
    
    print(df.to_json(orient='records', date_format='iso', date_unit='s'))
    
    # [{"0":"2018-01-01"}]
    

    我认为这是目前最好的方法,直到 pandas 添加一种仅写入超出日期时间的日期的方法。

    【讨论】:

    • 我认为 date_formatdate_unit kwargs 变得多余,因为 pandas 只看到一个字符串对象,而不是一个日期对象
    【解决方案3】:

    演示:

    来源 DF:

    In [249]: df = pd.DataFrame({
         ...:   'val':np.random.rand(5),
         ...:   'date1':pd.date_range('2018-01-01',periods=5),
         ...:   'date2':pd.date_range('2017-12-15',periods=5)
         ...: })
    
    In [250]: df
    Out[250]:
           date1      date2       val
    0 2018-01-01 2017-12-15  0.539349
    1 2018-01-02 2017-12-16  0.308532
    2 2018-01-03 2017-12-17  0.788588
    3 2018-01-04 2017-12-18  0.526541
    4 2018-01-05 2017-12-19  0.887299
    
    In [251]: df.dtypes
    Out[251]:
    date1    datetime64[ns]
    date2    datetime64[ns]
    val             float64
    dtype: object
    

    您可以在一个命令中将datetime 列转换为字符串:

    In [252]: df.update(df.loc[:, df.dtypes.astype(str).str.contains('date')].astype(str))
    
    In [253]: df.dtypes
    Out[253]:
    date1     object
    date2     object
    val      float64
    dtype: object
    
    In [254]: df.to_json(orient='records')
    Out[254]: '[{"date1":"2018-01-01","date2":"2017-12-15","val":0.5393488718},{"date1":"2018-01-02","date2":"2017-12-16","val":0.3085324043},{"
    date1":"2018-01-03","date2":"2017-12-17","val":0.7885879674},{"date1":"2018-01-04","date2":"2017-12-18","val":0.5265407505},{"date1":"2018-0
    1-05","date2":"2017-12-19","val":0.887298853}]'
    

    或者,您可以在 SQL 端将日期列转换为字符串

    【讨论】:

    • 谢谢 MaxU。我意识到这确实有效,但实际上,我有多个列和许多数据帧(都来自 SQL 查询),所以像这样硬编码列引用对我来说并不实用。
    • @user2242044,好吧,我认为无论如何你都必须将这些列转换为字符串 - 无论是在 SQL 端还是在 Pandas 中
    • 啊,我忘了我可以在 SQL 端做到这一点,这可能是最好的。谢谢。
    【解决方案4】:

    我也遇到过这个问题,但是由于我只查找日期,而忽略了时区,所以我可以使用以下表达式解决这个问题:

    df = pd.read_json('test.json')
    df['date_hour'] = [datetime.strptime(date[0:10],'%Y-%m-%d').date() for date in df['date_hour']]
    

    因此,如果您在 json 文件中有 df[date_hour] 的 'iso' date_format = "2018-01-01T00:00:00Z",则可以使用此解决方案。

    通过这种方式,您可以提取真正重要的部分。重要的是要说您必须使用此列表推导来执行此操作,因为转换只能逐个字符串(或逐行)完成,否则仅 datetime.strptime 会引发错误,说明不能与系列一起使用。

    【讨论】:

      【解决方案5】:

      通用解决方案如下:

      df.assign( **df.select_dtypes(['datetime']).astype(str).to_dict('list') ).to_json(orient="records")
      

      它根据 dtype 选择日期时间列并将它们设置为 str 对象,以便在序列化期间保持日期格式。

      【讨论】:

        猜你喜欢
        • 2017-01-17
        • 2018-10-20
        • 1970-01-01
        • 2021-03-26
        • 1970-01-01
        • 2021-09-27
        • 2021-07-20
        • 1970-01-01
        • 2021-05-22
        相关资源
        最近更新 更多