pandas读取json在MultiIndex上不起作用
我正在尝试通过 pd.read_json
来读取一个用 df.to_json()
创建的数据框(dataframe),但是遇到了 ValueError
错误。我觉得这可能和数据框的索引是多重索引(MultiIndex)有关,但我不太确定该怎么处理。
我原来的数据框有55000行,叫做 psi
,我通过以下方式创建了 test.json
:
psi.head().to_json('test.json')
如果你想使用,可以查看 这里,这是 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":
但是当我在整个数据框(55000行)上操作时,我得到了一个 无效指针错误,并且IPython内核崩溃了。有什么想法吗?
编辑:我添加了最初是如何生成这个json的内容。
4 个回答
这是我为处理多重索引的 pandas 数据框而做的一个简单粗糙的解决办法,这个方法似乎也适用于索引或列中包含日期时间的情况……不过并没有经过优化!
这里是把数据框编码成 JSON 的代码——我把数据框、索引和列都放进一个字典里,然后生成 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)
如果你想返回一个多重索引的结构:
# 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)
或者你可以直接用一种叫做'table'的方式来写json文件。
df.to_json(path_or_buf='test.json', orient='table')
读取多重索引的json文件
pd.read_json('test.json', orient='table')
这个功能现在还没有实现,具体情况可以查看这个链接:https://github.com/pydata/pandas/issues/4889。
你可以先重置索引,比如这样:
df.reset_index().to_json(...)
这样就可以正常工作了。