簡體   English   中英

將 JSON 轉換為 CSV 與復雜的 arrays 在 ZA7F5F35426B927411739231B56382

[英]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
    }
  }
]

結果如下所示:

CSV 輸出

您可以看到超過第一級的任何數組都顯示在 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM