在Python中将大型(140MB)JSON文件转换为CSV

问题描述 投票:0回答:2

我一直在尝试用大文件进行数据整理练习,我选择了这个大文件,我在谷歌上搜索了一下,发现它在Python中相当简单,但我还不是最熟悉编码的人。所以我需要更多关于如何正确设置它的解释(像我五岁一样解释)。我已经完成了“用另一个名称保存文件以对其进行格式化”,但这就是它的格式化方式。 This is how it is formatted as

我不确定从我找到的Python代码中它是否应该是这样的,所以,如果有人可以帮助或向我澄清它。这是我找到的代码。

import json
import csv
 
with open('G:\Akhil\jsonoutput.json') as json_file:
    jsondata = json.load(json_file)
 
data_file = open('G:\Akhil\jsonoutput.csv', 'w', newline='')
csv_writer = csv.writer(data_file)
 
count = 0
for data in jsondata:
    if count == 0:
        header = data.keys()
        csv_writer.writerow(header)
        count += 1
    csv_writer.writerow(data.values())
 
data_file.close()

该代码正确吗?如果是,我该如何编辑它来转换它?如何下载并保存该文件以便在 Excel 上打开它?预先感谢

这对我来说是新事物,所以我想弄清楚,但我陷入了困境,因为我什至不确定 JSON 文件的格式是否正确

python json csv type-conversion
2个回答
0
投票

将任何内容(JSON、XML...)转换为 CSV 时,您需要清楚地了解您希望最终的 CSV 是什么样子。

对于 JSON,这只是平面对象的列表:

[
    {"id": "1", "name": "foo", "score": 0},
    {"id": "2", "name": "bar", "score": 0},
    {"id": "1", "name": "foo", "score": 1},
    {"id": "3", "name": "baz", "score": 0},
    {"id": "3", "name": "baz", "score": 2}
]

我们可以轻松地将其可视化为以下 CSV:

id,name,score
1,foo,0
2,bar,0
1,foo,1
3,baz,0
3,baz,2

以及进行转换的 Python 代码:

import csv
import json

with open("input_flat.json") as f:
    data = json.load(f)

with open("output_flat.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=data[0].keys())
    writer.writeheader()
    for row in data:
        writer.writerow(row)

由于 JSON 只是一个对象数组,或者用 Python 术语来说,就是 字典列表,我们可以使用 DictWriter 在

row
中编写每个单独的字典 (
data
)。我们还必须使用它将在各个字典中查找的字段名来创建 DictWriter,因此
data[0].keys()
从数据中的第一个字典中获取键。

对于 JSON 来说更像你的,我们有一个嵌套结构,有点像:

{
    "1": {
        "name": "foo",
        "data": [
            {"score": 0},
            {"score": 1}
        ]
    },
    "2": {
        "name": "bar",
        "data": [
            {"score": 0}
        ]
    },
    "3": {
        "name": "baz",
        "data": [
            {"score": 0},
            {"score": 2}
        ]
    }
}

CSV 看起来应该与上面的 CSV 相似吗? (只有你,亲爱的程序员,可以回答这个问题)如果是这样,我们仍然可以像上面一样使用 DictWriter,但是现在 row-dict 没有交给我们,我们需要自己构建它:

with open("input_nested.json") as f:
    all_data = json.load(f)

rows = []
for id_, obj in all_data.items():
    for data in obj["data"]:
        row = {
            "id": id_,
            "name": obj["name"],
            "score": data["score"],
        }

        rows.append(row)

with open("output_nested.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=rows[0].keys())
    writer.writeheader()
    for row in rows:
        writer.writerow(row)

加载 JSON 时,我将数据重命名为 all_data。接下来,我们将 all_data 中的每个对象及其子对象(在“data”键下)“展平”为一行;或者,从结构的底部“构建”行字典。 (我还必须小心并在外循环中命名我的变量 id_,因为

id
是 Python 中的保留词。)这给了我们:
id,name,score
1,foo,0
1,foo,1
2,bar,0
3,baz,0
3,baz,2

由于排序原因,与上面的不完全相同,但几乎相等。

尽管搜索 OWID 大约 20 分钟,但我无法找到您使用的实际 JSON,但从您的屏幕截图来看,这些结构非常相似。如果您可以遵循简单的 foo-bar-baz 示例并了解嵌套 JSON 的结构,以及如何在 Python 中使用它,您就可以开始设计最终所需的 CSV。


0
投票
for data in jsondata

只是键,而不是要写入 CSV 的值。所以,for循环不起作用。

如果确实如此,那么

count = 0

事情就不太对劲了。您将标题写两次。通过将

values()
写入 CSV,您可以假设每个字典值始终以相同的顺序写入。但 JSON 字典没有排序,所以这个假设不起作用。
最好使用处理字典的

csv.DictWriter

。如果这是众所周知的 JSON 格式,最好在 Python 脚本中对标头进行硬编码。这将帮助脚本检测错误。但在这个例子中,我假设总是至少有一个条目,并且任何条目键都可以用于标题。

import json
import csv

# json data is a dict whose values are dicts to be written to a csv.

with open('G:\Akhil\jsonoutput.json') as json_file:
    jsondata = json.load(json_file)

# assuming all dicts have the same keys, grab the first one as header
fieldnames = next(jsondata.values())

with open('G:\Akhil\jsonoutput.csv', 'w', newline='') as data_file:
    csv_writer = csv.DictWriter(data_file, fieldnames)
    csv_writer.writerows(jsondata.values())

请注意,此代码忽略外部字典的键(“AFG”等)。如果您也需要该信息,可以在写入 CSV 之前将其添加到内部字典中。

© www.soinside.com 2019 - 2024. All rights reserved.