防止 Pandas to_json() 将时间组件添加到日期对象



>我有一个包含一些日期对象的数据帧。我需要转换为 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"}]

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

to_json无法只写过时的日期 #16492

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

您可以使用

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"}]

我认为这是目前最好的方法,直到熊猫添加一种仅写过时日期的方法。

演示:

来源自由度:

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 端的字符串

我也有这个问题,但由于我只寻找日期,丢弃时区,我能够使用以下表达式绕过它:

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 文件 = "2018-01-01T00:00:00Z" 中有 df[date_hour] 的"iso"date_format,则可以使用此解决方案。

通过这种方式,您可以提取真正重要的位。重要的是要说你必须使用此列表理解来完成,因为转换只能逐个字符串(或逐行(完成,否则,单独的datetime.strptime会抛出一个错误,说不能与系列一起使用。

通用解决方案如下:

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

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

最新更新