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 yaitucontinent
dengan nilai"Asia"
danregion
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 yaituname
,islands
danpopulation
.
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)