将Pandas DataFrame和元数据保存为JSON格式

时间:2015-10-13 20:46:51

标签: python json pandas

我需要将一个Pandas DataFrame以及一些元数据保存到JSON格式的文件中。 (JSON格式是必需的。)

背景
A)我可以使用DataFrame.to_json()DataFrame.from_json()从/向JSON成功读取/写入我相当大的Pandas Dataframe。没问题。

B)使用json.dump() / json.load()

将我的元数据(dict)保存到JSON没有问题


我的第一次尝试
由于Pandas不直接支持DataFrame元数据,我首先想到的是

top_level_dict = {}
top_level_dict['data'] = df.to_dict()
top_level_dict['metadata'] = {'some':'stuff'}
json.dump(top_level_dict, fp)


失败模式
C)我发现即使是

的简化案例
df_dict = df.to_dict()
json.dump(df_dict, fp)

失败了:

TypeError: key (u'US', 112, 5, 80, 'wl') is not a string

D)调查,我发现补充也失败了。

df.to_json(fp)
json.load(fp)

失败
384             raise ValueError("No JSON object could be decoded")
ValueError: Expecting : delimiter: line 1 column 17 (char 16)

所以看起来Pandas JSON格式和Python的JSON库不兼容。

我的第一个想法是追逐一种方法来修改 C df.to_dict()输出,使其适合Python的JSON库,但我一直听到“如果你正在努力在Python中做一些事情,你可能做错了。“在我脑海里。


问题
将元数据添加到Pandas DataFrame并存储到JSON格式文件的cannonical / recommended方法是什么?

Python 2.7.10
熊猫0.17

编辑1:
在尝试Evan Wright的答案时,我找到了问题的根源:Pandas(截至0.17)不喜欢将多索引数据框架保存为JSON。我创建的用于保存我的(多索引)数据框架的库在调用df.reset_index()之前正在安静地执行DataFrame.to_json()。我的新代码不是。因此在MultiIndex上进行DataFrame.to_json()打嗝。

课程:阅读文档小孩,即使它是您自己的文档。

编辑2:

如果您需要将DataFrame和元数据存储在单个 JSON对象中,请参阅下面的答案。

2 个答案:

答案 0 :(得分:2)

您应该能够将数据放在不同的行上。

写作:

f = open('test.json', 'w')
df.to_json(f)
print >> f
json.dump(metadata, f)

读:

f = open('test.json')
df = pd.read_json(next(f))
metdata = json.loads(next(f))

答案 1 :(得分:1)

在我的问题中,我错误地说我需要文件中的JSON。在那种情况下,Evan Wright的回答是我的首选解决方案。

就我而言,我实际上需要将JSON输出存储为数据库中的单个“blob”,因此我的字典争用方法似乎是必要的。

如果您同样需要将数据和元数据存储在单个JSON blob中,则以下代码将起作用:

top_level_dict = {}
top_level_dict['data'] = df.to_dict()
top_level_dict['metadata'] = {'some':'stuff'}
with open(FILENAME, 'w') as outfile:
    json.dump(top_level_dict, outfile)

确保DataFrame是单索引的。如果它是多重索引,请在执行上述操作之前重置索引(即df.reset_index())。

重读数据:

with open(FILENAME, 'r') as infile:
    top_level_dict = json.load(infile)

df_as_dict = top_level_dict.pop('data', {})
df = pandas.DataFrame().as_dict(df_as_dict)

meta = top_level_dict['metadata']

此时,您需要重新创建多指数(如果适用)