Python JSON到具有嵌套列表的数据帧
我运行下面的代码,它输出下面的jsonPython JSON到具有嵌套列表的数据帧,python,json,pandas,Python,Json,Pandas,我运行下面的代码,它输出下面的json import requests url="xxxx" r = requests.request("GET", url, headers=headers, data=payload) j=r.json() recs = j['collection'] Json {'stationCode': 'NB001', 'summaries': [{'period': {'year': 2017}, 'rain
import requests
url="xxxx"
r = requests.request("GET", url, headers=headers, data=payload)
j=r.json()
recs = j['collection']
Json
{'stationCode': 'NB001',
'summaries': [{'period': {'year': 2017}, 'rainfall': 449},
{'period': {'year': 2018}, 'rainfall': 352.4},
{'period': {'year': 2019}, 'rainfall': 253.2},
{'period': {'year': 2020}, 'rainfall': 283},
{'period': {'year': 2021}, 'rainfall': 104.2}]},{'stationCode': 'NA003','summaries': [{'period': {'year': 2019}, 'rainfall': 58.2},{'period': {'year': 2020}, 'rainfall': 628.2},{'period': {'year': 2021}, 'rainfall': 120}]}
我需要如下输出到一个表中
尝试了下面的方法,我仍然可以通过添加多行来提取表,但只是想知道是否有更快的方法
df = json_normalize(recs)
df
使用:
或:
In [955]: %timeit f1()
385 µs ± 20.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [969]: %timeit f2()
3.48 ms ± 224 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
分别解析rec
dict,这应该更有效:
In [952]: def f1():
...: s = []
...: y = []
...: r = []
...: for k,v in recs[0].items():
...: if k == 'stationCode':
...: s.append(v)
...: else:
...: for i in v:
...: y.append(i['period']['year'])
...: r.append(i['rainfall'])
...: s = s * len(y)
...: df = pd.DataFrame({'stationCode': s, 'year': y, 'rainfall':r})
两者的计时:
In [955]: %timeit f1()
385 µs ± 20.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [969]: %timeit f2()
3.48 ms ± 224 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
您可以为元组中的每个条目迭代(您共享的数据是dict的元组):
替代解决方案:我喜欢,因为它对json中一些粗糙的嵌套选项非常有用。使用jmespath
(它本身就是一种语言,有很多函数)的一个简短故事是,如果您正在访问一个键,则点进入播放,如果它是一个列表,则使用[]
符号:
import jmespath
expression = jmespath.compile("""{stationcode:stationCode,
year: summaries[].period.year,
rainfall: summaries[].rainfall}""")
outcome = [pd.DataFrame(expression.search(entry)) for entry in recs]
pd.concat(outcome)
stationcode year rainfall
0 NB001 2017 449.0
1 NB001 2018 352.4
2 NB001 2019 253.2
3 NB001 2020 283.0
4 NB001 2021 104.2
0 NA003 2019 58.2
1 NA003 2020 628.2
2 NA003 2021 120.0
只是你工具中的一个武器库,如果不能完全切断它的话。对于原始速度,内置的dict是王者。+1然而,这就是我的意思。可以用几行额外的线路来完成。有直接上升法吗?没有这样的直接上升法。另一种方法是解析
recs
以获得直接的dict
,而不是解析df
@wwnde中的列。请检查我的更新答案。也有时间安排。谢谢@Mayank Porwal,Wemmy的回答很有说服力。解压嵌套的json列表。感谢您的帮助@wwnde。毫无疑问,共享的数据是一个dict元组。如果你能分享正确的json格式,那就更好了。我明白你的意思了。除非我给你一个网址。把它等同于一个变量,它就是一个元组?逗号实际上就是一个元组。看起来你复制了它的一小部分(虽然这很好),很好的一个@sammywemmyNice答案。但这比解析recs
时的解决方案要慢;除此之外,json_normalize更为方便。如果您不介意将速度添加到您的解决方案中;这是一个很好的答案。@sammywemmy,很高兴发布一个问题。只是不想把它说出来,因为答案的质量很低。如果我有以下内容。如何将每个实体作为列获取?你似乎有相当多的武器库
import jmespath
expression = jmespath.compile("""{stationcode:stationCode,
year: summaries[].period.year,
rainfall: summaries[].rainfall}""")
outcome = [pd.DataFrame(expression.search(entry)) for entry in recs]
pd.concat(outcome)
stationcode year rainfall
0 NB001 2017 449.0
1 NB001 2018 352.4
2 NB001 2019 253.2
3 NB001 2020 283.0
4 NB001 2021 104.2
0 NA003 2019 58.2
1 NA003 2020 628.2
2 NA003 2021 120.0