[英]Convert JSON to CSV with complex arrays in Python
我有幾個帶有嵌套數據的 JSON 文件。 利用 Python,我能夠使用pandas
來幫助解決這個問題:
import pandas as pd
df = pd.read_json (r'data.json')
export_csv = df.to_csv (r'data.csv', index = None, header=True)
但是,這只適用於簡單的 JSON 文件。 我擁有的那些與嵌套的 arrays 和一些 JSON 數據合並在列下很復雜。 例如,如果我們要使用這個示例數據:
data.json
[
{
"id": 1,
"name": {
"english": "Bulbasaur",
"french": "Bulbizarre"
},
"type": [
"Grass",
"Poison"
],
"base": {
"HP": 45,
"Attack": 49,
"Defense": 49
}
},
{
"id": 2,
"name": {
"english": "Ivysaur",
"french": "Herbizarre"
},
"type": [
"Grass",
"Poison"
],
"base": {
"HP": 60,
"Attack": 62,
"Defense": 63
}
}
]
結果如下所示:
您可以看到超過第一級的任何數組都顯示在 JSON 中(例如{'english': 'Bulbasaur', 'french': 'Bulbizarre'}
)。 理想情況下,它應該將這些子 arrays 分解為具有元素名稱的列:
最重要的是,其他 JSON 文件具有不同的元素名稱和順序。 因此,腳本應該捕獲所有不同的元素名稱,然后將它們轉換為 CSV 列。
我怎樣才能做到這一點?
查看 flatten_json
from flatten_json import flatten
dic = [
{
"id": 1,
"name": {
"english": "Bulbasaur",
"french": "Bulbizarre"
},
"type": [
"Grass",
"Poison"
],
"base": {
"HP": 45,
"Attack": 49,
"Defense": 49
}
},
{
"id": 2,
"name": {
"english": "Ivysaur",
"french": "Herbizarre"
},
"type": [
"Grass",
"Poison"
],
"base": {
"HP": 60,
"Attack": 62,
"Defense": 63
}
}
]
dic_flattened = (flatten(d, '.') for d in dic)
df = pd.DataFrame(dic_flattened)
Output:
id name.english name.french type.0 type.1 base.HP base.Attack base.Defense
0 1 Bulbasaur Bulbizarre Grass Poison 45 49 49
1 2 Ivysaur Herbizarre Grass Poison 60 62 63
使用json_normalize會讓你幾乎到那里,但要拆分列表,你需要一些額外的東西:
f = lambda x: 'type.{}'.format(x + 1)
df = df.join(pd.DataFrame(df.pop('type').values.tolist()).rename(columns=f))
print(df)
Output
id name.english name.french ... base.Defense type.1 type.2
0 1 Bulbasaur Bulbizarre ... 49 Grass Poison
1 2 Ivysaur Herbizarre ... 63 Grass Poison
[2 rows x 8 columns]
我建議使用 for 循環和defaultdict ,在進行迭代(沒有聚合)時通常更容易和更快地遠離 pandas 直到最終的 output:
from collections import defaultdict
df = defaultdict(list)
val = {}
box = []
for entry in data: # data is the sample data you shared
for key, value in entry.items():
if key == "id":
temp = [(key, value)]
elif isinstance(value, dict):
temp = [(f"{key}.{k}", v) for k, v in value.items()]
else:
temp = [(f"{key}.{k}", v) for k, v in enumerate(value, 1)]
box.extend(temp)
for k, v in box:
df[k].append(v)
df
defaultdict(list,
{'id': [1, 2],
'name.english': ['Bulbasaur', 'Ivysaur'],
'name.french': ['Bulbizarre', 'Herbizarre'],
'type.1': ['Grass', 'Grass'],
'type.2': ['Poison', 'Poison'],
'base.HP': [45, 60],
'base.Attack': [49, 62],
'base.Defense': [49, 63]})
創建 dataframe
pd.DataFrame(df)
id name.english name.french type.1 type.2 base.HP base.Attack base.Defense
0 1 Bulbasaur Bulbizarre Grass Poison 45 49 49
1 2 Ivysaur Herbizarre Grass Poison 60 62 63
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.