熊猫读取 json 不适用于 MultiIndex

Posted

技术标签:

【中文标题】熊猫读取 json 不适用于 MultiIndex【英文标题】:pandas read json not working on MultiIndex 【发布时间】:2014-05-11 05:04:46 【问题描述】:

我正在尝试通过pd.read_json 读取通过df.to_json() 创建的数据框,但我得到的是ValueError。我认为这可能与索引是 MultiIndex 的事实有关,但我不确定如何处理。

55k 行的原始数据框称为psi,我通过以下方式创建了test.json

psi.head().to_json('test.json')

Here是print psi.head().to_string()的输出,如果你想使用的话。

当我对这一小组数据(5 行)执行此操作时,我得到一个 ValueError

! wget --no-check-certificate https://gist.githubusercontent.com/olgabot/9897953/raw/c270d8cf1b736676783cc1372b4f8106810a14c5/test.json
import pandas as pd
pd.read_json('test.json')

这是完整的堆栈:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-1de2f0e65268> in <module>()
      1 get_ipython().system(u' wget https://gist.githubusercontent.com/olgabot/9897953/raw/c270d8cf1b736676783cc1372b4f8106810a14c5/test.json'>)
      2 import pandas as pd
----> 3 pd.read_json('test.json')

/home/obot/virtualenvs/envy/lib/python2.7/site-packages/pandas/io/json.pyc in read_json(path_or_buf, orient, typ, dtype, convert_axes, convert_dates, keep_default_dates, numpy, precise_float, date_unit)
    196         obj = FrameParser(json, orient, dtype, convert_axes, convert_dates,
    197                           keep_default_dates, numpy, precise_float,
--> 198                           date_unit).parse()
    199 
    200     if typ == 'series' or obj is None:

/home/obot/virtualenvs/envy/lib/python2.7/site-packages/pandas/io/json.pyc in parse(self)
    264 
    265         else:
--> 266             self._parse_no_numpy()
    267 
    268         if self.obj is None:

/home/obot/virtualenvs/envy/lib/python2.7/site-packages/pandas/io/json.pyc in _parse_no_numpy(self)
    481         if orient == "columns":
    482             self.obj = DataFrame(
--> 483                 loads(json, precise_float=self.precise_float), dtype=None)
    484         elif orient == "split":
    485             decoded = dict((str(k), v)

ValueError: No ':' found when decoding object value

> /home/obot/virtualenvs/envy/lib/python2.7/site-packages/pandas/io/json.py(483)_parse_no_numpy()
    482             self.obj = DataFrame(
--> 483                 loads(json, precise_float=self.precise_float), dtype=None)
    484         elif orient == "split":

但是当我在整个数据帧(55k 行)上执行此操作时,我得到一个invalid pointer error 并且 IPython 内核死了。有什么想法吗?

编辑:首先添加了 json 的生成方式。

【问题讨论】:

这不是有效的 JSON。我想问题在于它最初是如何创建的。你有创建它的示例代码吗? 未实施,请参见此处:github.com/pydata/pandas/issues/4889 @Jeff:如果to_json 生成无效的 JSON 似乎仍然很糟糕。这是发生了什么,还是这里有其他错误? 嗯,这是阅读它。欢迎有 PR 来修复它(虽然它有点不重要)。 @Jeff:是的,但她说她使用to_json 创建了 JSON(但没有具体说明如何)。 【参考方案1】:

这不是 ATM 实现的,请在此处查看问题:https://github.com/pydata/pandas/issues/4889。

您可以简单地先重置索引,例如

df.reset_index().to_json(...)

它会起作用的。

【讨论】:

它不适用于 pandas 1.3.0 我在使用 df.reset_index().to_json(orient="table") 时收到错误 NotImplementedError: orient='table' is not supported for MultiIndex columns【参考方案2】:

或者你可以用 orient = 'table' 写 json

df.to_json(path_or_buf='test.json', orient='table')

读取多索引json

pd.read_json('test.json', orient='table')

【讨论】:

它为我加载了满是 NaN 的表=(但具有与初始 df 相同的 MultiIndex 结构。 在 pandas 1.0.1 中获取 NotImplementedError: orient='table' is not supported for MultiIndex 我相信使用 pandas v1+,您需要提供 typ == 'frame' 然后它接受 orient 表。 pandas.pydata.org/docs/reference/api/…【参考方案3】:

如果要返回 MultiIndex 结构:

 # save MultiIndex indexes names 
 indexes_names = df.index.names

 df.reset_index().to_json('dump.json')

 # return back MultiIndex structure:
 loaded_df = pd.read_json('dump.json').set_index(indexes_names)

【讨论】:

如果你在一个系列中使用名称,它会生成一个只有 1 级的冻结集。如果你简单地执行以下操作,这将有效:pd.read_json('series.json').set_index(series.index)【参考方案4】:

这是我对多索引熊猫数据帧进行编码/解码的简单脏修复,它似乎也适用于索引/列中的日期时间...未优化!

这里是 json 的编码器 - 我将数据帧、索引和列编码到 dict 中以创建 json

import json
import pandas as pd

def to_json_multiindex(df):
    dfi = df.index.to_frame()
    dfc = df.columns.to_frame()

    d = dict(
        df = df.to_json(),
        di = dfi.to_json(),
        dc = dfc.to_json()   
    )

    return json.dumps(d)

同时这里是读取 json 字典并重新创建数据帧的解码器

def read_json_multiindex(j):
    d = json.loads(j)

    di=pd.read_json(d['di'])
    if di.shape[1]>1:
        di = pd.MultiIndex.from_frame(di)
    else:
        _name = di.columns[0]
        di = di.index
        di.name = _name
        
        
    dc=pd.read_json(d['dc'])
    if dc.shape[1]>1:
        dc = pd.MultiIndex.from_frame(dc)
    else:
        _name = dc.columns[0]
        dc = dc.index
        dc.name = _name        
    
    df = pd.read_json(d['df']).values
    
    return pd.DataFrame(
        data=df,
        index=di,
        columns=dc,
    )

这是对多索引列和索引的测试...似乎保留了数据框。几个问题 1) 可能效率低下,2) 似乎确实适用于多索引中的数据时间(但在它不是多索引时有效)

    df = pd.DataFrame(
        data = [[0,1,2],[2,3,4],[5,6,7]],
        index = pd.MultiIndex.from_tuples(
           (('aa','bb'),('aa','cc'),('bb','cc')
        ),
        names=['AA','BB']),
        columns = pd.MultiIndex.from_tuples(
           (('XX','YY'),('XX','ZZ'),('YY','ZZ')
        ),
        names=['YY','ZZ'])
    )
    
    j = to_json_multiindex(df)
    d = read_json_multiindex(j)

【讨论】:

以上是关于熊猫读取 json 不适用于 MultiIndex的主要内容,如果未能解决你的问题,请参考以下文章

如果存在多索引,熊猫将不允许选择列?

折叠熊猫 MultiIndex

熊猫 iloc 和 loc & multiindex

通过 MultiIndex 选择熊猫

熊猫系列 sort_index() 不适用于 kind='mergesort'

熊猫查询功能不适用于列名中的空格