Membuka Data dalam format JSON dengan Python

Membuka Data dalam format JSON dengan Python

Format JSON

JSON atau Javascript Object Notation merupakan format yang umum digunakan untuk pertukaran data antara sisi client dan server. Dalam konteks data science banyak sekali data (misalkan dari kaggle) yang tersedia dalam format JSON. Selain itu, sebagian besar data yang diambil dari output penyedia layanan API juga memiliki format JSON.

Format ini didasarkan pada sintaksis objek pada JavaScript, namun dapat digunakan dengan berbagai bahasa pemrograman lainnya. JSON sendiri menggunakan struktur data berbasis pasangan key-value. Data disusun dalam bentuk objek (dalam tanda kurung kurawal) atau dalam bentuk array (dalam tanda kurung siku). Setiap pasangan kunci-nilai dalam objek dipisahkan oleh tanda koma, sedangkan elemen-elemen dalam array juga dipisahkan oleh tanda koma.

Berikut ini contoh data dalam format JSON:

JSON

{
  "name": "Indonesia",
  "capital": "Jakarta",
  "area": 1904569,
  "population": 273523615
}

Data di atas merupakan contoh sederhana dari format json. Data terdiri dari 6 key yaitu "name", "alpha_2", "alpha_3", "capital", "area", dan "population" dengan masing-masing value yaitu "Indonesia", "ID", "IDN", "Jakarta", 1904569 dan 273523615. Dokumen seperti ini biasa disebut dokumen single level dimana setiap key memiliki nilai tunggal.

Di sisi lain, terdapat dokumen JSON multilevel yang lebih kompleks dimana nilai untuk suatu key dapat berisi pasangan key-value lainnya.

JSON

{
  "name": "Indonesia",
  "capital": "Jakarta",
  "geography": {
    "continent": "Asia",
    "region": "Southeast Asia"
  },
  "languages": ["Indonesian", "Javanese", "Sundanese"],
  "provinces": [
    {
      "name": "Aceh",
      "islands": "Sumatera",
      "population": 4494410
    },
    {
      "name": "Bali",
      "islands": "Bali & Nusa Tenggara",
      "population": 4225000
    },
    {
      "name": "West Java",
      "islands" : "Java"
      "population": 48634000
    }
  ]
}

Contoh di atas menunjukkan dokumen JSON yang lebih kompleks dan terdiri dari beberapa level. Penjelasan masing-masing key dari dokumen tersebut adalah sebagai berikut:

  • name, capital masing-masing memiliki nilai tunggal yaitu string dan numerik.
  • geography memiliki nilai berupa pasangan key-value lainnya yaitu continent dengan nilai "Asia" dan region dengan nilai "Southeast Asia"
  • languages memiliki nilai berupa list yang terdiri dari tiga elemen yaitu ["Indonesian", "Javanese", "Sundanese"]
  • provinces memiliki nilai berupa list dengan 3 elemen, dimana setiap elemen didalamnya juga terdiri dari pasangan key-value yaitu name, islands dan population.

Fungsi json.load

Di dalam bahasa Python format JSON memiliki struktur yang serupa dengan tipe data dict (dictionary), pada module python json, ketika membaca sebuah dokumen JSON maka akan disimpan sebagai tipe data dict atau list[dict].

Untuk mencobanya, silahkan simpan contoh dokumen JSON di atas dengan nama apapun, misal indonesia.json. Kita dapat membuka file tersebut menggunakan sintaks berikut ini:

Script

import json
# (misal file berada pada direktori yang sama)
# membuka file "indonesia.json dengan mode read
# menyimpan isi file sebagai objek json pada variabel idn

with open("user.json", 'r') as file:
    idn = json.load(file)

print(idn)
print(type(idn))
print(idn['name'])
print(idn.get('population'))

Output

# OUTPUT

{
 'name': 'Indonesia', 
 'capital': 'Jakarta', 
 'area': 1904569, 
 'population': 273523615
}

<class 'dict'>

Indonesia
273523615

Pada kode di atas kita membaca file JSON yang sederhana, kemudian dengan fungsi load objek disimpan pada variabel idn. Variabel idn ini memiliki tipe data dict sehingga setiap isiannya dapat diakses seperti data dict pada umumnya menggunakan [key] atau metode b`.

Contoh lainnya, misalkan file JSON dengan nama asean.json berisi daftar beberapa negara dalam bentuk list seperti berikut ini:

JSON

[
  {
    "name": "Indonesia",
    "capital": "Jakarta",
    "area": 1904569,
    "population": 273523615
  },
  {
    "name": "Malaysia",
    "capital": "Kuala Lumpur",
    "area": 330803,
    "population": 32365999
  },
  {
    "name": "Singapore",
    "capital": "Singapore",
    "area": 728,
    "population": 5850342
  },
  {
    "name": "Thailand",
    "capital": "Bangkok",
    "area": 513120,
    "population": 69799978
  },
  {
    "name": "Vietnam",
    "capital": "Hanoi",
    "area": 331212,
    "population": 97338579
  }
]

Dengan cara yang sama kita dapat membaca file tersebut seperti berikut ini:

Script

# membuka file "asean.json dengan mode read
# contoh file berada pada direktori yang sama
# menyimpan isi file sebagai objek json pada variabel asean

with open("asean.json", 'r') as file:
    asean = json.load(file)

# mencetak data setiap negara
for country in asean:
    print(country)

# mencetak name dan capital elemen ke-2 (malaysia)
print(asean[1]["name"])
print(asean[1]["capital"])

Output

# OUTPUT

{'name': 'Indonesia', 'capital': 'Jakarta', 'area': 1904569, 'population': 273523615}
{'name': 'Malaysia', 'capital': 'Kuala Lumpur', 'area': 330803, 'population': 32365999}
{'name': 'Singapore', 'capital': 'Singapore', 'area': 728, 'population': 5850342}
{'name': 'Thailand', 'capital': 'Bangkok', 'area': 513120, 'population': 69799978}
{'name': 'Vietnam', 'capital': 'Hanoi', 'area': 331212, 'population': 97338579}

Malaysia
Kuala Lumpur

Pada contoh di atas, variabel asean merupakan list dimana setiap elemennya berupa dict dengan key yang sama seperti contoh sebelumnya. Data yang sudah dimuat kemudian dapat diproses menggunakan fitur-fitur yang ada pada list maupun dict.

Fungsi pandas.read_json (1 Level)

Berbicara mengenai pengolahan data menggunakan python, maka satu pustaka yang paling banyak digunakan tentu saja adalah pandas. Pustaka pandas sendiri memiliki beberapa fungsi yang dapat membaca dokumen JSON menjadi dataframe.

Untuk membaca dokumen JSON sebagai dataframe, kita dapat menggunakan fungsi read_json. Berikut contoh kode untuk melakukannya:

Python

# memuat pustaka pandas
import pandas as pd

data = pd.read_json("asean.json")

print(data)

Output

# OUTPUT

        name       capital     area  population
0  Indonesia       Jakarta  1904569   273523615
1   Malaysia  Kuala Lumpur   330803    32365999
2  Singapore     Singapore      728     5850342
3   Thailand       Bangkok   513120    69799978
4    Vietnam         Hanoi   331212    97338579

Fungsi read_json juga dapat digunakan pada data dengan format horizontal dimana setiap key memiliki nilai berupa list. Misalkan data negara ASEAN yang sama kita simpan dalam format horizontal dengan nama asean_h.json seperti contoh berikut:

JSON

{
  "name": ["Indonesia", "Malaysia", "Singapore", "Thailand", "Vietnam"],
  "capital": ["Jakarta", "Kuala Lumpur", "Singapore", "Bangkok", "Hanoi"],
  "area": [1904569, 330803, 728, 513120, 331212],
  "population": [273523615, 32365999, 5850342, 69799978, 97338579]
}

Dengan kode yang sama, walaupun dokumen JSON memiliki format berbeda maka kita akan tetap menghasilkan dataframe dalam bentuk yang sama pula.

Script

data = pd.read_json("asean_h.json")

print(data)

Fungsi pandas.read_json (Bersarang)

Dalam beberapa kasus, dokumen JSON yang perlu diolah mungkin lebih kompleks dan terdiri dari beberapa level. Fungsi read_json memang masih bisa menangani dokumen seperti ini namun terdapat beberapa kekurangan yang mungkin akan menyulitkan dalam pengolahan selanjutnya.

Misalkan kita memiliki dokumen JSON asean_complex.json yang mirip seperti sebelumnya, namun nilai untuk key population bukan berupa 1 nilai melainkan beberapa nilai yang mencerminkan jumlah penduduk pada tahun tertentu (2018, 2019, 2020).

JSON

[
  {
    "name": "Indonesia",
    "capital": "Jakarta",
    "area": 1904569,
    "population": {
      "2018": 267670543,
      "2019": 271350000,
      "2020": 274480000
    }
  },
  {
    "name": "Malaysia",
    "capital": "Kuala Lumpur",
    "area": 330803,
    "population": {
      "2018": 31813750,
      "2019": 31949700,
      "2020": 32064400
    }
  },
  {
    "name": "Singapore",
    "capital": "Singapore",
    "area": 728,
    "population": {
      "2018": 5638676,
      "2019": 5703569,
      "2020": 5757494
    }
  },
  {
    "name": "Thailand",
    "capital": "Bangkok",
    "area": 513120,
    "population": {
      "2018": 69799978,
      "2019": 69870000,
      "2020": 69950000
    }
  },
  {
    "name": "Vietnam",
    "capital": "Hanoi",
    "area": 331212,
    "population": {
      "2018": 95540395,
      "2019": 96208984,
      "2020": 97338579
    }
  }
]

Kita dapat membaca data tersebut seperti sebelumnya menggunakan fungsi read_json, dan akan menghasilkan output seperti berikut ini:

Script

data = pd.read_json("asean_complex.json")

data

Output

 name          capital        area   population  
0  Indonesia       Jakarta  1904569  {'2018': 267670543, '2019': 271350000, '2020':...
1   Malaysia  Kuala Lumpur   330803  {'2018': 31813750, '2019': 31949700, '2020': 3...
2  Singapore     Singapore      728  {'2018': 5638676, '2019': 5703569, '2020': 575...  
3   Thailand       Bangkok   513120  {'2018': 69799978, '2019': 69870000, '2020': 6...
4    Vietnam         Hanoi   331212  {'2018': 95540395, '2019': 96208984, '2020': 9...

Berdasarkan output di atas dapat dilihat bahwa kolom population menyimpan sekaligus data jumlah penduduk untuk tahun 2018, 2019 dan 2020 dengan type dict. Hal ini tentu membuat tabel lebih sulit dibaca, serta menyulitkan ketika akan dilakukan pengolahan data lebih lanjut untuk kolom tersebut.

Sebagai contoh, jika kita ingin menghitung total penduduk kelima negara ASEAN untuk setiap tahunnya. Maka sintaks yang diperlukan adalah sebagai berikut:

Script

# Menghitung total populasi 5 negara ASEAN Tahun 2018, 2019, 2020
tot_2018 = data['population'].apply(lambda tahun: tahun['2018']).sum()
tot_2019 = data['population'].apply(lambda tahun: tahun['2019']).sum()
tot_2020 = data['population'].apply(lambda tahun: tahun['2020']).sum()

print(tot_2018, tot_2019, tot_2020)

# OUTPUT
# 470463342 475082253 479590473

Solusi yang lebih baik tentunya kita dapat mengekstrak nilai populasi setiap tahun menjadi kolom tersendiri misalkan menjadi pop_2018, pop_2019 dan pop_2020.

Kode berikut ini merupakan cara manual yang dapat dilakukan untuk mengekstrak data dari kolom population.

Script

# Menambah kolom baru dan menghapus kolom population
data["pop_2018"] = data["population"].apply(lambda tahun: tahun['2018'])
data["pop_2019"] = data["population"].apply(lambda tahun: tahun['2019'])
data["pop_2020"] = data["population"].apply(lambda tahun: tahun['2020'])
data.drop(columns=["population"], inplace=True)

print(data)

Output

# OUTPUT

        name       capital     area   pop_2018   pop_2019   pop_2020
0  Indonesia       Jakarta  1904569  267670543  271350000  274480000
1   Malaysia  Kuala Lumpur   330803   31813750   31949700   32064400
2  Singapore     Singapore      728    5638676    5703569    5757494
3   Thailand       Bangkok   513120   69799978   69870000   69950000
4    Vietnam         Hanoi   331212   95540395   96208984   97338579

Walaupun dataframe yang diperoleh sudah memudahkan untuk pengolahan lebih lanjut, namun proses awal untuk ekstraksi data pada kolom population masih cukup rumit. Kita perlu mengetahui setiap key pada kolom tersebut. Cara yang lebih baik untuk menangani permasalahan tersebut adalah menggunakan fungsi json_normalize.

Fungsi pandas.json_normalize

Pustaka pandas menyediakan cara lainnya untuk mengekstrak dokumen JSON yang memiliki banyak level yaitu menggunakan fungsi json_normalize. Fungsi ini memerlukan argumen berupa dict atau list[dict] maka kita perlu memuat dokumen JSON dan menyimpannya dalam type list[dict] terlebih dahulu. Cara yang dapat dilakukan yaitu memuat dokumen fungsi load dari module json.

Berikut kode untuk mengekstrak data pada dokumen asean_complex.json dan menyimpan setiap nilai menjadi kolom tersendiri tidak peduli sedalam apa level dari data tersebut.

Script

# membuka file "asean_complex.json dengan mode read
# menyimpan isi file sebagai objek json pada variabel asean

with open("asean_complex.json", "r") as file:
    asean = json.load(file)

# membuat dataframe dari objek json
data = pd.json_normalize(asean)

print(data)

Output

# OUTPUT

       name        capital     area  population.2018  population.2019  population.2020   
0  Indonesia       Jakarta  1904569        267670543        271350000        274480000
1   Malaysia  Kuala Lumpur   330803         31813750         31949700         32064400
2  Singapore     Singapore      728          5638676          5703569          5757494
3   Thailand       Bangkok   513120         69799978         69870000         69950000
4    Vietnam         Hanoi   331212         95540395         96208984         97338579

Pertama kita membuka file asean_complex.json dengan mode read, selanjutnya dengan menggunakan fungsi load pada module json kita simpan objek tersebut ke dalam variabel asean. Selanjutnya buat dataframe dengan nama b` menggunakan fungsi json_normalize.

Fungsi json_normalize memungkinkan kita untuk membuat kolom pada dataframe berdasarkan setiap key walaupun key tersebut berada pada level yang lebih dalam. Penamaan kolom secara default merupakan kombinasi dari key pada setiap levelnya. Seperti pada contoh ini, key pada level pertama yaitu population, dimana didalamnya terdapat 3 key lagi yaitu 2018, 2019 dan 2020, sehingga nama kolom yang diberikan adalah population.2018, population.2019 dan population.2020.

Sebagai alternatif, jika hanya ingin menggunakan pandas tanpa tambahan pustaka json dapat dilakukan dengan mengombinasikan fungsi read_json dan json_normalize, seperti berikut ini:

Script

# membaca file dalam format json
data = pd.read_json("asean_complex.json")

# melakukan proses normalize pada kolom population
# menyimpan hasilnya dalam dataframe data_pop
data_pop = pd.json_normalize(data["population"])

# memperbarui data dengan menghapus kolom population dan
# menggabungkan dengan data_pop hasil normalize
data = pd.concat([data.drop('population', axis=1), data_pop], axis=1)


print(data)

Output

# OUTPUT

        name       capital     area       2018       2019       2020
0  Indonesia       Jakarta  1904569  267670543  271350000  274480000
1   Malaysia  Kuala Lumpur   330803   31813750   31949700   32064400
2  Singapore     Singapore      728    5638676    5703569    5757494
3   Thailand       Bangkok   513120   69799978   69870000   69950000
4    Vietnam         Hanoi   331212   95540395   96208984   97338579

Pada contoh di atas, pertama kita mengunakan fungsi json_rmalize untuk mengubah kolom population dan menyimpannya ke dalam variabel data_prop. Variabel ini akan menghasilkan dataframe dengan 3 kolom sesuai isian kolom population yaitu 2018, 2019 dan 2020.

Selanjutnya, kita melakukan update pada variabel data dengan menghapus kolom population serta menggabungkannya dengan variabel data_pop. Nilai parameter axis=1 baik pada method drop, maupun fungsi concat menunjukan kita bekerja secara kolom (drop kolom, dan concat kolom).

Judul kolom baru yang dihasilkan mungkin kurang mendeskripsikan maksud isiannya, untuk menghindari kebingungan kita dapat merubah judul-judul kolom menggunakan fungsi rename.

Script

# merubah nama kolom 2018, 2019, 2020
data.rename(columns={"2018": "pop_2018", 
                     "2019": "pop_2019", 
                     "2020": "pop_2020"}, 
             inplace=True)

print(data)

Output

# OUTPUT

        name       capital     area   pop_2018   pop_2019   pop_2020
0  Indonesia       Jakarta  1904569  267670543  271350000  274480000
1   Malaysia  Kuala Lumpur   330803   31813750   31949700   32064400
2  Singapore     Singapore      728    5638676    5703569    5757494
3   Thailand       Bangkok   513120   69799978   69870000   69950000
4    Vietnam         Hanoi   331212   95540395   96208984   97338579

Dengan memiliki dataframe dalam format yang lebih rapi maka pengolahan dapat dilakukan menjadi lebih mudah, misalkan untuk agregasi, grouping, sorting dan sebagainya. Selain itu kita dapat pula menyimpan data tersebut ke dalam format lain misalkan ke dalam format csv seperti contoh berikut:

Script

# menyimpan data dalam format csv
data.to_csv("data_asean.csv", index=False)

Tulisan Lainnya

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

Daftar Isi