【问题标题】:How do I keep the timezone of my index when serializing/deserializing a Pandas DataFrame using JSON使用 JSON 序列化/反序列化 Pandas DataFrame 时如何保持索引的时区
【发布时间】:2017-05-20 11:47:45
【问题描述】:

我需要使用 to_json 方法将 Pandas DataFrame 序列化为 JSON。这是我如何做的一个例子:

import pandas
import numpy as np
dr = pandas.date_range('2016-01-01T12:30:00Z', '2016-02-01T12:30:00Z')
data = np.random.rand(len(dr), 2)
df = pandas.DataFrame(data, index=dr, columns=['a', 'b'])

# NOTE: The index for df has the following properties in pandas 0.19.2
#       dtype='datetime64[ns, UTC]', freq='D'

# Save to JSON
df.to_json('/tmp/test_data_01.json', date_unit='s', date_format='iso')

使用上面的代码,我看到我的 DataFrame 已保存到磁盘,并且索引看起来像:[2016-01-01T12:30:00Z, 2016-01-02T12:30:00Z, ...] in文件 /tmp/test_data_01.json。

问题是当我执行以下操作时:

df2 = pandas.read_json('/tmp/test_data_01.json')

df2 的索引没有时区。

df2.index.tz
# Returns None

是否要保留序列化为 JSON 并反序列化的 DataFrame 的 timezone 属性?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    使用to_json 时,Pandas 会将所有内容转换为 UTC。

    查看这个示例,我将其更改为 Europe/Paris,即 UTC+1:

    In [1]:
    dr = pd.date_range('2016-01-01T12:30:00Z', '2016-02-01T12:30:00Z')
    dr = dr.tz_convert('Europe/Paris')
    data = np.random.rand(len(dr), 2)
    df = pd.DataFrame(data, index=dr, columns=['a', 'b'])
    
    In [2]: df.index[0]
    Out[2]: Timestamp('2016-01-01 13:30:00+0100', tz='Europe/Paris', freq='D')
    
    In [3]: df.to_json('test_data_01.json', date_unit='s', date_format='iso')
    

    如果我打开test_data_01.json,第一个是"2016-01-01T12:30:00Z"。

    因此,当您加载 json 时,请将其本地化为 UTC。虽然没有办法知道事先使用了什么 tz:

    In [4]:
    df2 = pd.read_json('test_data_01.json')
    df2.index = df2.index.tz_localize('UTC')
    

    【讨论】:

    • 从 2020 年中期开始,pandas 现在支持使用orient='table' 在 JSON 导出中使用时区。请看下面我的回答
    【解决方案2】:

    我不同意@julien-marrec 的解决方案,因为它强制时区为UTC,而在调用read_json 时,时区可以是其他任何东西。我在分析时区时实施了以下解决方法来解析日期。

    import pandas._libs.json as json
    loads = json.loads
    result = loads('{"2019-01-01T13:00:00.000Z":15,"2019-01-01T11:00:00.000Z":88.352985054,"2019-01-01T12:00:00.000Z":90.091719896}',
              dtype=None, numpy=True, labelled=True )
    pd.Series(result[0], pd.DatetimeIndex(result[1])).index
    

    并填写了一个关于 https://github.com/pandas-dev/pandas/issues/25546 的错误

    【讨论】:

      【解决方案3】:

      从 PR #35973 开始,(我认为是 1.2.0 版)使用 orient='table' 参数时现在支持时区。

      import pandas as pd
      import numpy as np
      
      dr = pd.date_range("2020-08-30", freq="d", periods=4, tz="Europe/London")
      data = np.random.rand(len(dr), 2)
      df = pd.DataFrame(data, index=dr, columns=['a', 'b'])
      
      print(df)
      print(pd.read_json(df.to_json(orient='table'), orient='table'))  # same output!
      

      【讨论】:

        猜你喜欢
        • 2018-06-14
        • 2014-10-29
        • 1970-01-01
        • 1970-01-01
        • 2012-10-30
        • 1970-01-01
        • 1970-01-01
        • 2015-01-18
        相关资源
        最近更新 更多