从深度嵌套的 JSON 创建 Pandas DataFrame
Posted
技术标签:
【中文标题】从深度嵌套的 JSON 创建 Pandas DataFrame【英文标题】:Create a Pandas DataFrame from deeply nested JSON 【发布时间】:2014-02-24 23:19:21 【问题描述】:我正在尝试从深度嵌套的 JSON 字符串创建单个 Pandas DataFrame 对象。
JSON 架构是:
"intervals": [
pivots: "Jane Smith",
"series": [
"interval_id": 0,
"p_value": 1
,
"interval_id": 1,
"p_value": 1.1162791357932633e-8
,
"interval_id": 2,
"p_value": 0.0000028675012051504467
],
,
"pivots": "Bob Smith",
"series": [
"interval_id": 0,
"p_value": 1
,
"interval_id": 1,
"p_value": 1.1162791357932633e-8
,
"interval_id": 2,
"p_value": 0.0000028675012051504467
]
]
期望结果我需要将其展平以生成表格:
Actor Interval_id Interval_id Interval_id ...
Jane Smith 1 1.1162 0.00000 ...
Bob Smith 1 1.1162 0.00000 ...
第一列为Pivots
的值,其余列为interval_id
和p_value
存储在列表series
中的键值。
目前为止
import requests as r
import pandas as pd
actor_data = r.get("url/to/data").json['data']['intervals']
df = pd.DataFrame(actor_data)
actor_data
是一个长度等于个体数量的列表,即pivots.values()
。 df 对象简单地返回
<bound method DataFrame.describe of pivots Series
0 Jane Smith [u'p_value': 1.0, u'interval_id': 0, u'p_va...
1 Bob Smith [u'p_value': 1.0, u'interval_id': 0, u'p_va...
.
.
.
如何遍历 series
列表以获取 dict 值并创建 N 个不同的列?我是否应该尝试为series
列表创建一个DataFrame,对其进行整形,然后使用演员名称进行列绑定?
更新:
pvalue_list = [i['p_value'] for i in json_data['series']]
这给了我一个列表列表。现在我需要弄清楚如何将每个列表添加为 DataFrame 中的一行。
value_list = []
for i in pvalue_list:
pvs = [j['p_value'] for j in i]
value_list = value_list.append(pvs)
return value_list
这会返回一个 NoneType
解决方案
def get_hypthesis_data():
raw_data = r.get("/url/to/data").json()['data']
actor_dict =
for actor_series in raw_data['intervals']:
actor = actor_series['pivots']
p_values = []
for interval in actor_series['series']:
p_values.append(interval['p_value'])
actor_dict[actor] = p_values
return pd.DataFrame(actor_dict).T
这将返回正确的 DataFrame。我转置了它,所以个人是行而不是列。
【问题讨论】:
list.append
方法不返回任何内容(嗯,它返回 None
因为所有 Python 函数都返回一些内容),因为它会就地更新列表。只需删除value_list =
,您的列表就会正确更新。
【参考方案1】:
我认为以产生重复列名的方式组织数据只会让您日后感到头疼。恕我直言,更好的方法是为 pivots
、interval_id
和 p_value
中的每一个创建一个列。这将使您在将数据加载到 pandas 后查询数据变得非常容易。
另外,您的 JSON 中有一些错误。我通过this 运行它以查找错误。
jq
在这里帮助
import sh
jq = sh.jq.bake('-M') # disable colorizing
json_data = "from above"
rule = """[pivots: .intervals[].pivots,
interval_id: .intervals[].series[].interval_id,
p_value: .intervals[].series[].p_value]"""
out = jq(rule, _in=json_data).stdout
res = pd.DataFrame(json.loads(out))
这将产生类似于
的输出 interval_id p_value pivots
32 2 2.867501e-06 Jane Smith
33 2 1.000000e+00 Jane Smith
34 2 1.116279e-08 Jane Smith
35 2 2.867501e-06 Jane Smith
36 0 1.000000e+00 Bob Smith
37 0 1.116279e-08 Bob Smith
38 0 2.867501e-06 Bob Smith
39 0 1.000000e+00 Bob Smith
40 0 1.116279e-08 Bob Smith
41 0 2.867501e-06 Bob Smith
42 1 1.000000e+00 Bob Smith
43 1 1.116279e-08 Bob Smith
改编自this comment
当然,您可以随时调用res.drop_duplicates()
来删除重复的行。这给了
In [175]: res.drop_duplicates()
Out[175]:
interval_id p_value pivots
0 0 1.000000e+00 Jane Smith
1 0 1.116279e-08 Jane Smith
2 0 2.867501e-06 Jane Smith
6 1 1.000000e+00 Jane Smith
7 1 1.116279e-08 Jane Smith
8 1 2.867501e-06 Jane Smith
12 2 1.000000e+00 Jane Smith
13 2 1.116279e-08 Jane Smith
14 2 2.867501e-06 Jane Smith
36 0 1.000000e+00 Bob Smith
37 0 1.116279e-08 Bob Smith
38 0 2.867501e-06 Bob Smith
42 1 1.000000e+00 Bob Smith
43 1 1.116279e-08 Bob Smith
44 1 2.867501e-06 Bob Smith
48 2 1.000000e+00 Bob Smith
49 2 1.116279e-08 Bob Smith
50 2 2.867501e-06 Bob Smith
[18 rows x 3 columns]
【讨论】:
哇,使用jq
真是太好了!我觉得我越来越近了。如果我将jq
规则更改为rule = """[.intervals[].series]"""
,这将允许我构建一个具有正确 N x K 维度的 DataFrame。问题是每个单元格都是一个字典,例如 u'p_value': 1, u'interval_id': 0
而不仅仅是 p_value
的值。
这对DataFrame
来说应该不是问题。
有没有办法改变单元格的值,使它们只包含p_value
的值而不是整个字典?
我不确定你的意思。你能举个例子说明你在说什么吗?
@Anton:不确定自 2014 年初以来发生了什么变化,但据我所知,jq
不接受字符串作为命令行参数。相反,您可以创建一个cat = sh.cat
,然后将其通过管道传输到jq
:jq(cat(_in=json_data), rule).stdout
。见amoffat.github.io/sh/#piping以上是关于从深度嵌套的 JSON 创建 Pandas DataFrame的主要内容,如果未能解决你的问题,请参考以下文章
如何从带有列表的嵌套 Json 创建 pandas DataFrame