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

zc0qhyus  于 2023-06-19  发布在  Python
关注(0)|答案(2)|浏览(163)

我一直在尝试用大文件做一个数据争论练习,我选择了这个大文件,我在谷歌上搜索了一下,发现它在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文件的格式是否正确

carvr3hs

carvr3hs1#

你有几个问题。首先,您的数据看起来像一个字典,其值是您想要写入CSV的字典。for data in jsondata只是键,而不是您想要写入CSV的值。因此,for循环将不起作用。
如果是的话,count = 0就不太对了。你写了两次标题。通过将values()写入CSV,您假设每个dict值总是以相同的顺序写入。但是JSON dict不是有序的,所以这个假设不起作用。
最好使用处理字典的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())

请注意,这段代码忽略了外部dict的键("AFG"等)。如果您也需要这些信息,可以在CSV写入之前将其添加到内部dicts中。

kupeojn6

kupeojn62#

在将任何东西(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,其中包含它将在各个dict中查找的字段名,因此data[0].keys()从数据中的第一个dict中获取键。
对于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时将data重命名为all_data。接下来,我们 flatten all_data中的每个对象,以及其子对象(在“data”键下),降到一行;或者从结构的底部“构建”行字典。(我还必须小心,在外部循环中命名我的变量id_,因为id在Python中是resevered word。)这给了我们:

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

由于排序的原因,与上面的不完全相同,但几乎相等。
我无法找到你使用的实际JSON,尽管搜索了大约20分钟的OWID,但从你的截图来看,这些结构非常相似。如果您能够沿着简单的foo-bar-baz示例并理解嵌套JSON的结构,然后了解如何在Python中使用它,则可以开始设计最终的所需CSV。

相关问题