如何从一个文件中读取多个 JSON 数据列表到 Pandas
Posted
技术标签:
【中文标题】如何从一个文件中读取多个 JSON 数据列表到 Pandas【英文标题】:How to read multiple lists of JSON data from one file into Pandas 【发布时间】:2020-11-05 06:51:15 【问题描述】:我有一个从 Twitter 的 API 收集 JSON 数据的脚本。该脚本每分钟收集数据并使用jq
对其进行解析。这些数据被收集到一个文件中,最终如下所示:
[
"text": "Tweet 01",
"id": "001"
,
"text": "Tweet 02",
"id": "002"
,
"text": "Tweet 03",
"id": "003"
]
[
"text": "Tweet 04",
"id": "004"
,
"text": "Tweet 05",
"id": "005"
,
"text": "Tweet 06",
"id": "006"
,
"text": "Tweet 07",
"id": "007"
,
"text": "Tweet 08",
"id": "008"
]
[
"text": "Tweet 09",
"id": "009"
,
"text": "Tweet 10",
"id": "010"
]
我以前每个文件都有一个 JSON 数据列表,Pandas 可以轻松处理文件中的一个列表。但是如何有效地遍历这些不是逗号分隔且长度不一定相同的多个列表?
我的最终目标是聚合这个文件中的所有 JSON 数据并将其转换为 CSV 文件,其中每一列都是 JSON 数据中的一个键。它最终应该看起来像:
text, id
Tweet 01, 001
Tweet 02, 002
Tweet 03, 003
Tweet 04, 004
Tweet 05, 005
Tweet 06, 006
Tweet 07, 007
Tweet 08, 008
Tweet 09, 009
Tweet 10, 010
如果我还是要尝试读取文件,则会发生以下情况:
>>> import pandas as pd
>>> df = pd.read_json("sample.json")
>>> df.head()
Traceback (most recent call last):
File "lists.py", line 3, in <module>
df = pd.read_json("sample.json")
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pandas/util/_decorators.py", line 214, in wrapper
return func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pandas/io/json/_json.py", line 608, in read_json
result = json_reader.read()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pandas/io/json/_json.py", line 731, in read
obj = self._get_object_parser(self.data)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pandas/io/json/_json.py", line 753, in _get_object_parser
obj = FrameParser(json, **kwargs).parse()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pandas/io/json/_json.py", line 857, in parse
self._parse_no_numpy()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pandas/io/json/_json.py", line 1089, in _parse_no_numpy
loads(json, precise_float=self.precise_float), dtype=None
ValueError: Trailing data
【问题讨论】:
可能的解决方案在这里使用JSONDecoder.raw_decode
:***.com/questions/27907633/…。 JSON 不是用于附加此类数据的好格式,除非您不漂亮地打印并使每个 json 成为单行。您还可以在记录之间添加自己的装饰,例如“===============”,以便在获取 json 之前拆分文件。但实际上,选择更好的格式。一个简单的 CSV 在这里可以很好地工作。
【参考方案1】:
正如@Trenton McKinney 所说,您需要清理数据。因此,您可以使用f.read()
将文件作为字符串获取,然后使用str.replace()
将']\n['
替换为','
,因为']\n['
会导致错误,最后
你可以试试pd.read_json
:
with open('data.json') as f:
data=f.read()
data=data.replace(']\n[',',')
df=pd.read_json(data)
输出:
df
0 Tweet 01 1
1 Tweet 02 2
2 Tweet 03 3
3 Tweet 04 4
4 Tweet 05 5
5 Tweet 06 6
6 Tweet 07 7
7 Tweet 08 8
8 Tweet 09 9
9 Tweet 10 10
【讨论】:
【参考方案2】: 需要将文件内容转换为标准列表,方法是读入文件并将各个列表转换为单个列表。.readlines
读取文件的每一行作为字符串列表
使用list comprehension 遍历每一行,使用str.strip
删除字符串前后的空格和换行符。
str.join
将列表中的项目组合成一个字符串。
str.replace
将 ']['
替换为 ','
。
使用ast.literal_eval
将字符串转换回列表。
from ast import literal_eval
import pandas as pd
# open and clean the contents of the file
with open('test.json', 'r') as f:
data = literal_eval(''.join([row.strip() for row in f.readlines()]).replace('][', ','))
# print(data)
['text': 'Tweet 01', 'id': '001',
'text': 'Tweet 02', 'id': '002',
'text': 'Tweet 03', 'id': '003',
'text': 'Tweet 04', 'id': '004',
'text': 'Tweet 05', 'id': '005',
'text': 'Tweet 06', 'id': '006',
'text': 'Tweet 07', 'id': '007',
'text': 'Tweet 08', 'id': '008',
'text': 'Tweet 09', 'id': '009',
'text': 'Tweet 10', 'id': '010']
# load into pandas
df = pd.json_normalize(data)
# display(df)
text id
0 Tweet 01 001
1 Tweet 02 002
2 Tweet 03 003
3 Tweet 04 004
4 Tweet 05 005
5 Tweet 06 006
6 Tweet 07 007
7 Tweet 08 008
8 Tweet 09 009
9 Tweet 10 010
【讨论】:
【参考方案3】:只要原始 json 文件适合内存,您就可以使用raw_decoder
将 json 列表拉出,一次一个。 raw_decoder
返回解析中消耗的数据长度,您可以修剪字符串并继续直到没有数据剩余。
import csv
import json
with open('data.json') as f:
rawdata = f.read()
decoder = json.JSONDecoder().raw_decode
with open('data.csv','w') as f:
writer = csv.DictWriter(f, fieldnames=["id", "text"])
while rawdata:
data, idx = decoder(rawdata)
writer.writerows(data)
rawdata = rawdata[idx:].lstrip()
print(open('data.csv').read())
【讨论】:
以上是关于如何从一个文件中读取多个 JSON 数据列表到 Pandas的主要内容,如果未能解决你的问题,请参考以下文章
python - 如何在python中附加一个列表时处理异常,其中包含从存储从.json文件读取的数据的dict读取的数据?