Pengolahan Data dangan Python : Pandas vs Polars
Pandas
dan polars
adalah dua pustaka pengolahan data yang tersedia pada bahasa python. Pandas
merupakan satu nama yang bisa dianggap sebagai alat standar de facto pemrosesan data. Pustaka ini menyediakan berbagai fungsi dan metode yang lengkap untuk membaca, memanipulasi, dan menganalisis hingga visualisasi data tabular.
Di sisi lain, polars
merupakan pustaka yang ditulis dalam bahasa Rust sehingga memberi performa dan kecepatan sebaik C/C++. Pustaka ini dirancang untuk pemrosesan data dengan kinerja tinggi serta skalabilitas. Sintaks yang digunakan dibuat relatif mirip dengan pandas
.
Polars
menawarkan eksekusi yang cepat dengan memanfaatkan teknik vektorisasi. Teknik ini memungkinkan pengguna untuk melakukan operasi data lebih cepat dan efisien bahkan untuk dataset yang besar. Walaupun saat ini fitur yang disediakan polars
belum selengkap pandas
, namun untuk fitur-fitur utama pemrosesan data sudah tersedia dengan performa yang jauh lebih cepat.
Pada tutorial ini kita akan membandingkan sintaksis pada pandas
dan polars
untuk melakukan pengolahan data. Tentu saja tidak semua hal dapat tercakup, namun di sini akan dijelaskan beberapa pengolahan yang umum dilakukan meliputi manipulasi data, slicing, filtering, agregating serta grouping data.
Pustaka pandas
dan polars
dapat dimuat menggunakan sintaks di bawah ini. Sudah menjadi konvensi yang umum untuk pandas
diberi alias pd
sedangkan polars
dengan alias pl
.
Python
# %pip install pandas pyarrow polars import pandas as pd import polars as pl
Python
print(pd.__version__) # 2.0.2 print(pl.__version__) # 0.18.0
Versi yang digunakan saat ini adalah pandas 2.0.2
serta polars 0.18.0
. Sebagai tambahan, selain menginstal pandas
dan polars
, kita juga dapat menginstal pustaka pyarrow
. Secara default pandas
akan menggunakan engine numpy
, namun mulai versi 2.0
kita dapat mengatur agar pandas
menggunakan engine pyarrow
dalam pemrosesan. Terdapat peningkatan performa pada beberapa proses pandas
khususnya yang berhubungan dengan operasi pada data string, termasuk juga kecepatan dalam membaca data csv.
MEMBANGKITKAN DATA
Sintaks berikut digunakan untuk membangkitkan data sintetis yang akan kita pakai sepanjang tutorial ini. Secara umum kita akan membangkitkan dataset acak yang terdiri dari 10 juta record dengan 5 buah fitur. Data disimpan dalam format CSV untuk keperluan pengolahan selanjutnya.
Python
# N: int = 10_000_000 # list_negara = [ # "Indonesia", # "Amerika Serikat", # "Perancis", # "Jepang", # "Brasil", # "Inggris", # "Kanada", # "Australia", # "India", # "Jerman", # ] # list_pekerjaan = [ # "Dokter", # "Guru", # "Programmer", # "Pilot", # "Desainer", # "Akuntan", # "Polisi", # "Pengusaha", # ] # data = pd.DataFrame( # { # "id": [f"SD{num:08}" for num in range(1, N + 1)], # "asal": np.random.choice(list_negara, size=N), # "gender": np.random.choice(["M", "F"], size=N), # "pekerjaan": np.random.choice(list_pekerjaan, size=N), # "gaji": np.random.exponential(scale=1000, size=N), # "pengalaman": np.random.randint(0, 35, size=N), # } # ) # data.to_csv("fake_data.csv", index=False)
MEMBACA DATA CSV
Pandas
dan polars
memiliki method read_csv
yang berguna untuk membaca file CSV. Terdapat beberapa pengaturan tambahan yang bisa digunakan pada masing-masing method. Namun di sini kita akan menggunakan setiap pengaturan secara default.
Sebagai informasi tambahan, kita akan memuat data dengan 3 cara, yaitu menggunakan pandas
dengan engine default, kedua (sebagai tambahan) masih menggunakan pandas namun dengan mengatur engine
dan dtype_backend
menjadi pyarrow
.
Python
# read data using pandas and default engine (numpy) data_pd = pd.read_csv("fake_data.csv") # read data using pandas and pyarrow engine # set dtype as pyarrow dtype data_ar = pd.read_csv("fake_data.csv", engine="pyarrow", dtype_backend="pyarrow") # read data using polars data_pl = pl.read_csv("fake_data.csv") print(data_pd.info()) print(data_ar.info()) print(data_pl.glimpse())
Output
# OUTPUT <class 'pandas.core.frame.DataFrame'> RangeIndex: 10000000 entries, 0 to 9999999 Data columns (total 6 columns): # Column Dtype --- ------ ----- 0 id object 1 asal object 2 gender object 3 pekerjaan object 4 gaji float64 5 pengalaman int64 dtypes: float64(1), int64(1), object(4) memory usage: 457.8+ MB ================================================================= <class 'pandas.core.frame.DataFrame'> RangeIndex: 10000000 entries, 0 to 9999999 Data columns (total 6 columns): # Column Dtype --- ------ ----- 0 id string[pyarrow] 1 asal string[pyarrow] 2 gender string[pyarrow] 3 pekerjaan string[pyarrow] 4 gaji double[pyarrow] 5 pengalaman int64[pyarrow] dtypes: double[pyarrow](1), int64[pyarrow](1), string[pyarrow](4) memory usage: 549.1 MB ================================================================= Rows: 10000000 Columns: 6 $ id <str> SD00000001, SD00000002, SD00000003, SD00000004, .... $ asal <str> Jerman, Brasil, Perancis, Jerman, Perancis, $ gender <str> F, M, M, M, M, F, M, F, M, M, ... $ pekerjaan <str> Programmer, Akuntan, Akuntan, Guru, Dokter, ... $ gaji <f64> 110.33639368940689, 1063.8895772881397, ... $ pengalaman <i64> 24, 16, 23, 28, 22, 19, 0, 24, 14, 0, ...
Terdapat perbedaan tipe data untuk setiap objek dataframe yang sudah dimuat. Jika kita tidak menentukan dtype
setiap kolom secara spesifik, pandas
akan memberikan tipe data object
untuk kolom-kolom yang berisi data non-numerik. Adapun pada engine pyarrow
, secara default akan dijadikan string
.
Pada sintaks-sintaks selanjutnya kita hanya akan menggunakan data data_pd
dan data_pl
saja, karena pada dasarnya data_ar
adalah objek dataframe pandas
, hanya berbeda engine yang digunakan dalam pemrosesan data (numpy
dan pyarrow
). Jika ingin menggunakan data_ar
maka sintaks yang sama dapat digunakan cukup dengan mengganti nama variabelnya saja.
MODIFIKASI DATAFRAME
Pustaka pandas
maupun polars
sama-sama memiliki fitur yang lengkap untuk proses modifikasi data. Termasuk di dalamnya, menambah kolom baru, mengupdate kolo serta menghapus kolom yang tidak diperlukan.
Menambah/Update Kolom
Terdapat perbedaan cara untuk menambah kolom baru ataupun memodifikasi kolom yang ada pada pandas
dan polars
. Pada pandas
kita dapat langsung memberikan nilai kolom baru sesuai nama kolom yang diinginkan.
Seperti contoh untuk menambah kolom baru gaji_thn
yang berisi nilai gaji dalam 1 tahun (gaji
x 12), maka kita cukup menggunakan sintaks data_pd["gaji_thn"] = ...
.
Contoh lainnya misal kita ingin mengupdate isian pada kolom gender
menjadi (L
sebagai pengganti M
) dan ()P
sebagai pengganti F
) maka cukup dengan sintaks data["gender"] = ...
.
Kita juga dapat melakukan update hanya pada kondisi tertentu saja. Misalkan kita ingin mengganti nilai kolom pekerjaan
khusus untuk "Programmer'
diupdate menjadi "Koder"
.
Sementara itu, pada polars
proses yang diperlukan tidak sesederhana itu. Penambahan kolom dapat dilakukan melalui method with_columns
. Setiap argumen di dalam method tersebut menunjukkan operasi pada kolom-kolom dataframe. Proses penambahan atau modifikasi isian kolom dapat menggunakan method apply
seperti hal nya pada pandas
.
Khusus untuk kolom dengan tipe string
, kedua pustaka juga menyediakan berbagai fungsi manipulasi yang dapat di akses pada method str
. Contohnya adalah fungsi replace
yang digunakan pada sintaks di bawah ini.
Python
# PANDAS # menambah kolom gaji_thn data_pd["gaji_thn"] = data_pd["gaji"] * 12 # update kolom "gender" menjadi "L" dan "P" data_pd["gender"] = data_pd["gender"].apply(lambda x: "L" if x == "M" else "P") # update kolom "id" (misal : mengganti SD menjadi 'X-') data_pd["id"] = data_pd["id"].str.replace("SD", "XID") # update kolom "pekerjaan" : # jika programmer ubah menjadi koder # jika bukan maka biarkan tetap sama data_pd["pekerjaan"] = data_pd["pekerjaan"].apply( lambda x: "Koder" if x == "Programmer" else x ) # POLARS data_pl = data_pl.with_columns( pl.col("gaji").apply(lambda x: x * 12).alias("gaji_thn"), pl.col("gender").apply(lambda x: "L" if x == "M" else "P"), pl.col("id").str.replace("SD", "XID"), pl.col("pekerjaan").apply(lambda x: "Koder" if x == "Programmer" else x), ) print(data_pd, f"{'*'*80}", data_pl, sep="\n\n") # f"{'*'*80}" : untuk mencetak tanda "*" sebanyak 80x # kita gunakan untuk memperjelas visual saja
Output
# OUTPUT id asal gender pekerjaan gaji \ 0 XID00000001 Jerman P Koder 110.336394 1 XID00000002 Brasil L Akuntan 1063.889577 2 XID00000003 Perancis L Akuntan 3058.718340 3 XID00000004 Jerman L Guru 1855.441910 4 XID00000005 Perancis L Dokter 1213.089917 ... ... ... ... ... ... 9999995 XID09999996 Indonesia L Koder 927.468371 9999996 XID09999997 Amerika Serikat L Polisi 526.675626 9999997 XID09999998 India P Koder 3748.563698 9999998 XID09999999 Kanada L Polisi 1.105699 9999999 XID10000000 Inggris P Akuntan 2427.333728 pengalaman gaji_thn 0 24 1324.036724 1 16 12766.674927 2 23 36704.620084 3 28 22265.302914 4 22 14557.079010 ... ... ... 9999995 19 11129.620453 9999996 20 6320.107511 9999997 25 44982.764376 9999998 10 13.268386 9999999 20 29128.004739 [10000000 rows x 7 columns] ******************************************************************************** shape: (10_000_000, 7) ┌─────────────┬─────────────────┬────────┬───────────┬─────────────┬────────────┬──────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman ┆ gaji_thn │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 ┆ f64 │ ╞═════════════╪═════════════════╪════════╪═══════════╪═════════════╪════════════╪══════════════╡ │ XID00000001 ┆ Jerman ┆ P ┆ Koder ┆ 110.336394 ┆ 24 ┆ 1324.036724 │ │ XID00000002 ┆ Brasil ┆ L ┆ Akuntan ┆ 1063.889577 ┆ 16 ┆ 12766.674927 │ │ XID00000003 ┆ Perancis ┆ L ┆ Akuntan ┆ 3058.71834 ┆ 23 ┆ 36704.620084 │ │ XID00000004 ┆ Jerman ┆ L ┆ Guru ┆ 1855.44191 ┆ 28 ┆ 22265.302914 │ │ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │ │ XID09999997 ┆ Amerika Serikat ┆ L ┆ Polisi ┆ 526.675626 ┆ 20 ┆ 6320.107511 │ │ XID09999998 ┆ India ┆ P ┆ Koder ┆ 3748.563698 ┆ 25 ┆ 44982.764376 │ │ XID09999999 ┆ Kanada ┆ L ┆ Polisi ┆ 1.105699 ┆ 10 ┆ 13.268386 │ │ XID10000000 ┆ Inggris ┆ P ┆ Akuntan ┆ 2427.333728 ┆ 20 ┆ 29128.004739 │ └─────────────┴─────────────────┴────────┴───────────┴─────────────┴────────────┴──────────────┘
Sering kali, kolom baru yang akan dibuat memerlukan operasi yang lebih rumit. Misal kita perlu menghitung total jumlah pajak yang harus dibayarkan. Adapun besaran jumlah pajak bervariasi tergantung gaji yang diterima. Misal untuk gaji < 1000
dikanakan pajak 5%, untuk gaji antara 1000
hingga 5000
dikenakan pajak 10% dan di atas 5000
dikenakan pajak 20%.
Proses ini dapat dilakukan dengan membuat fungsi tersendiri. Kemudian fungsi tersebut dimasukkan sebagai argumen pada method apply
.
Python
# Fungsi untuk menghitung tax def calculate_tax(gaji): if gaji < 1000: return gaji * 0.05 elif 1000 <= gaji <= 5000: return gaji * 0.10 else: return gaji * 0.20 # PANDAS data_pd["tax"] = data_pd["gaji"].apply(calculate_tax) # POLARS data_pl = data_pl.with_columns( pl.col("gaji").apply(calculate_tax).alias("tax"), ) print(data_pd, f"{'*'*80}", data_pl, sep="\n\n")
Output
# OUTPUT id asal gender pekerjaan gaji \ 0 XID00000001 Jerman P Koder 110.336394 1 XID00000002 Brasil L Akuntan 1063.889577 2 XID00000003 Perancis L Akuntan 3058.718340 3 XID00000004 Jerman L Guru 1855.441910 4 XID00000005 Perancis L Dokter 1213.089917 ... ... ... ... ... ... 9999995 XID09999996 Indonesia L Koder 927.468371 9999996 XID09999997 Amerika Serikat L Polisi 526.675626 9999997 XID09999998 India P Koder 3748.563698 9999998 XID09999999 Kanada L Polisi 1.105699 9999999 XID10000000 Inggris P Akuntan 2427.333728 pengalaman gaji_thn tax 0 24 1324.036724 5.516820 1 16 12766.674927 106.388958 2 23 36704.620084 305.871834 3 28 22265.302914 185.544191 4 22 14557.079010 121.308992 ... ... ... ... 9999995 19 11129.620453 46.373419 9999996 20 6320.107511 26.333781 9999997 25 44982.764376 374.856370 9999998 10 13.268386 0.055285 9999999 20 29128.004739 242.733373 [10000000 rows x 8 columns] ******************************************************************************** shape: (10_000_000, 8) ┌────────────┬────────────┬────────┬───────────┬────────────┬────────────┬────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman ┆ gaji_thn ┆ tax │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 ┆ f64 ┆ f64 │ ╞════════════╪════════════╪════════╪═══════════╪════════════╪════════════╪════════════╪════════════╡ │ XID0000000 ┆ Jerman ┆ P ┆ Koder ┆ 110.336394 ┆ 24 ┆ 1324.03672 ┆ 5.51682 │ │ 1 ┆ ┆ ┆ ┆ ┆ ┆ 4 ┆ │ │ XID0000000 ┆ Brasil ┆ L ┆ Akuntan ┆ 1063.88957 ┆ 16 ┆ 12766.6749 ┆ 106.388958 │ │ 2 ┆ ┆ ┆ ┆ 7 ┆ ┆ 27 ┆ │ │ XID0000000 ┆ Perancis ┆ L ┆ Akuntan ┆ 3058.71834 ┆ 23 ┆ 36704.6200 ┆ 305.871834 │ │ 3 ┆ ┆ ┆ ┆ ┆ ┆ 84 ┆ │ │ XID0000000 ┆ Jerman ┆ L ┆ Guru ┆ 1855.44191 ┆ 28 ┆ 22265.3029 ┆ 185.544191 │ │ 4 ┆ ┆ ┆ ┆ ┆ ┆ 14 ┆ │ │ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │ │ XID0999999 ┆ Amerika ┆ L ┆ Polisi ┆ 526.675626 ┆ 20 ┆ 6320.10751 ┆ 26.333781 │ │ 7 ┆ Serikat ┆ ┆ ┆ ┆ ┆ 1 ┆ │ │ XID0999999 ┆ India ┆ P ┆ Koder ┆ 3748.56369 ┆ 25 ┆ 44982.7643 ┆ 374.85637 │ │ 8 ┆ ┆ ┆ ┆ 8 ┆ ┆ 76 ┆ │ │ XID0999999 ┆ Kanada ┆ L ┆ Polisi ┆ 1.105699 ┆ 10 ┆ 13.268386 ┆ 0.055285 │ │ 9 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │ │ XID1000000 ┆ Inggris ┆ P ┆ Akuntan ┆ 2427.33372 ┆ 20 ┆ 29128.0047 ┆ 242.733373 │ │ 0 ┆ ┆ ┆ ┆ 8 ┆ ┆ 39 ┆ │ └────────────┴────────────┴────────┴───────────┴────────────┴────────────┴────────────┴────────────┘
Menghapus Kolom
Penghapusan kolom pada pandas
dapat menggunakan method drop
. dengan argumen berupa nama kolom (jika satu kolom) atau list nama kolom (jika banyak kolom) yang akan dihapus. Selain itu perlu mengatur axis=1
yang menginformasikan pandas
untuk melakukan penghapusan pada sisi kolom.
Pada polars
kita dapat mengunakan method select
. Method select
memungkin kita untuk menentukan kolom mana yang akan diikutkan, ataupun kolom mana yang akan dikeluarkan. Informasi kolom-kolom yang akan dikeluarkan dituliskan melalui argumen pada method pl.exlude
.
Python
# PANDAS data_pd = data_pd.drop(["tax", "gaji_thn"], axis=1) # POLARS data_pl = data_pl.select([pl.exclude(["tax", "gaji_thn"])]) print(data_pd, f"{'*'*80}", data_pl, sep="\n\n")
Output
# OUTPUT id asal gender pekerjaan gaji \ 0 XID00000001 Jerman P Koder 110.336394 1 XID00000002 Brasil L Akuntan 1063.889577 2 XID00000003 Perancis L Akuntan 3058.718340 3 XID00000004 Jerman L Guru 1855.441910 4 XID00000005 Perancis L Dokter 1213.089917 ... ... ... ... ... ... 9999995 XID09999996 Indonesia L Koder 927.468371 9999996 XID09999997 Amerika Serikat L Polisi 526.675626 9999997 XID09999998 India P Koder 3748.563698 9999998 XID09999999 Kanada L Polisi 1.105699 9999999 XID10000000 Inggris P Akuntan 2427.333728 pengalaman 0 24 1 16 2 23 3 28 4 22 ... ... 9999995 19 9999996 20 9999997 25 9999998 10 9999999 20 [10000000 rows x 6 columns] ******************************************************************************** shape: (10_000_000, 6) ┌─────────────┬─────────────────┬────────┬───────────┬─────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪═════════════════╪════════╪═══════════╪═════════════╪════════════╡ │ XID00000001 ┆ Jerman ┆ P ┆ Koder ┆ 110.336394 ┆ 24 │ │ XID00000002 ┆ Brasil ┆ L ┆ Akuntan ┆ 1063.889577 ┆ 16 │ │ XID00000003 ┆ Perancis ┆ L ┆ Akuntan ┆ 3058.71834 ┆ 23 │ │ XID00000004 ┆ Jerman ┆ L ┆ Guru ┆ 1855.44191 ┆ 28 │ │ … ┆ … ┆ … ┆ … ┆ … ┆ … │ │ XID09999997 ┆ Amerika Serikat ┆ L ┆ Polisi ┆ 526.675626 ┆ 20 │ │ XID09999998 ┆ India ┆ P ┆ Koder ┆ 3748.563698 ┆ 25 │ │ XID09999999 ┆ Kanada ┆ L ┆ Polisi ┆ 1.105699 ┆ 10 │ │ XID10000000 ┆ Inggris ┆ P ┆ Akuntan ┆ 2427.333728 ┆ 20 │ └─────────────┴─────────────────┴────────┴───────────┴─────────────┴────────────┘
SLICING DATAFRAME
Proses slicing adalah memotong atau mengambil bagian-bagian tertentu pada data untuk alasan tertentu. Berikut ini adalah beberapa fitur yang dapat digunakan untuk mengambil beberapa bagian tertentu dari sebuah dataframe.
Mengambil n-data pertama, terakhir dan sampel acak
Kedua pustaka memiliki method dengan nama yang sama untuk mengambil sejumlah data pertama, sejumlah data terakhir serta mengambil sejumlah sampel acak dari dataframe yaitu head
, tail
dan sample
.
Python
# Mengambil n data pertama & n data terakhir # pandas head_pd = data_pd.head(2) # n-first tail_pd = data_pd.tail(2) # n-last sample_pd = data_pd.sample(2) # n-sample random # polars head_pl = data_pl.head(2) # n-first tail_pl = data_pl.tail(2) # n-last sample_pl = data_pl.sample(2) # n-sample random print( head_pd, tail_pd, sample_pd, f"{'*'*80}", head_pl, tail_pl, sample_pl, sep="\n\n", )
Output
# OUTPUT id asal gender pekerjaan gaji pengalaman 0 XID00000001 Jerman P Koder 110.336394 24 1 XID00000002 Brasil L Akuntan 1063.889577 16 id asal gender pekerjaan gaji pengalaman 9999998 XID09999999 Kanada L Polisi 1.105699 10 9999999 XID10000000 Inggris P Akuntan 2427.333728 20 id asal gender pekerjaan gaji pengalaman 6338996 XID06338997 Jepang P Polisi 1091.317117 10 6820928 XID06820929 Jerman P Desainer 164.824865 1 ******************************************************************************** shape: (2, 6) ┌─────────────┬────────┬────────┬───────────┬─────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪════════╪════════╪═══════════╪═════════════╪════════════╡ │ XID00000001 ┆ Jerman ┆ P ┆ Koder ┆ 110.336394 ┆ 24 │ │ XID00000002 ┆ Brasil ┆ L ┆ Akuntan ┆ 1063.889577 ┆ 16 │ └─────────────┴────────┴────────┴───────────┴─────────────┴────────────┘ shape: (2, 6) ┌─────────────┬─────────┬────────┬───────────┬─────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪═════════╪════════╪═══════════╪═════════════╪════════════╡ │ XID09999999 ┆ Kanada ┆ L ┆ Polisi ┆ 1.105699 ┆ 10 │ │ XID10000000 ┆ Inggris ┆ P ┆ Akuntan ┆ 2427.333728 ┆ 20 │ └─────────────┴─────────┴────────┴───────────┴─────────────┴────────────┘ shape: (2, 6) ┌─────────────┬────────┬────────┬───────────┬────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪════════╪════════╪═══════════╪════════════╪════════════╡ │ XID02613860 ┆ India ┆ L ┆ Pilot ┆ 270.337283 ┆ 22 │ │ XID06940847 ┆ Jerman ┆ L ┆ Akuntan ┆ 284.988956 ┆ 5 │ └─────────────┴────────┴────────┴───────────┴────────────┴────────────┘
Pada pandas
kita dapat melakukan slicing menggunakan iloc
, loc
ataupun dengan list nama-nama kolom. Adapun pada polars
, proses slicing
dapat dilakukan secara langsung dengan menentukan indeks baris dan kolomnya, atau menggunakan kombinasi method select
dan slice
. Method select
digunakan untuk membatasi kolom yang dipilih dan slice
untuk membatasi baris yang dipilih.
Mendapatkan data pada baris pertama
Python
# mengambil data pada baris pertama # index baris = 0 # PANDAS sl_pd = data_pd.iloc[0] # POLARS sl_pl = data_pl[0] print(sl_pd, f"{'*'*80}", sl_pl, sep="\n\n")
Output
# OUTPUT id XID00000001 asal Jerman gender P pekerjaan Koder gaji 110.336394 pengalaman 24 Name: 0, dtype: object ******************************************************************************** shape: (1, 6) ┌─────────────┬────────┬────────┬───────────┬────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪════════╪════════╪═══════════╪════════════╪════════════╡ │ XID00000001 ┆ Jerman ┆ P ┆ Koder ┆ 110.336394 ┆ 24 │ └─────────────┴────────┴────────┴───────────┴────────────┴────────────┘
Mengambil data pada indeks baris ke-101 sampai 106 (5 data) dan semua kolom:
Python
# Mengambil data dengan indeks ke 101 sampai 106 (5 data) # PANDAS sl_pd = data_pd.iloc[101:106] # POLARS sl_pl = data_pl[101:106] # atau # sl_pl = data_pl.slice(101, 5) # slice(offset=101, length=5) print(sl_pd, f"{'*'*80}", sl_pl, sep="\n\n")
Output
id asal gender pekerjaan gaji pengalaman 101 XID00000102 Brasil P Desainer 275.007296 28 102 XID00000103 Brasil L Guru 802.384161 31 103 XID00000104 Indonesia L Guru 848.621492 21 104 XID00000105 Jerman L Polisi 600.041421 8 105 XID00000106 Jerman P Dokter 111.512057 21 ******************************************************************************** shape: (5, 6) ┌─────────────┬───────────┬────────┬───────────┬────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪═══════════╪════════╪═══════════╪════════════╪════════════╡ │ XID00000102 ┆ Brasil ┆ P ┆ Desainer ┆ 275.007296 ┆ 28 │ │ XID00000103 ┆ Brasil ┆ L ┆ Guru ┆ 802.384161 ┆ 31 │ │ XID00000104 ┆ Indonesia ┆ L ┆ Guru ┆ 848.621492 ┆ 21 │ │ XID00000105 ┆ Jerman ┆ L ┆ Polisi ┆ 600.041421 ┆ 8 │ │ XID00000106 ┆ Jerman ┆ P ┆ Dokter ┆ 111.512057 ┆ 21 │ └─────────────┴───────────┴────────┴───────────┴────────────┴────────────┘
Mengambil data pada indeks baris ke-101 sampai 106 untuk kolom "asal"
, "pekerjaan"
dan "gaji"
(indeks kolom ke-1, ke-3, dan ke-4):
Python
# slicing by index location and particular columns # PANDAS sl_pd = data_pd.iloc[101:106, [1, 3, 4]] # atau # sl_pd = data_pd[["asal", "pekerjaan", "gaji"]][101:106] # POLARS sl_pl = data_pl[101:106, [1, 3, 4]] # atau # sl_pl = data_pl.slice(101, 5).select(["asal", "pekerjaan", "gaji"]) # sl_pl = data_pl.select(["asal", "pekerjaan", "gaji"]).slice(101, 5) print(sl_pd, f"{'*'*80}", sl_pl, sep="\n\n")
Output
# OUTPUT asal pekerjaan gaji 101 Brasil Desainer 275.007296 102 Brasil Guru 802.384161 103 Indonesia Guru 848.621492 104 Jerman Polisi 600.041421 105 Jerman Dokter 111.512057 ******************************************************************************** shape: (5, 3) ┌───────────┬───────────┬────────────┐ │ asal ┆ pekerjaan ┆ gaji │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ f64 │ ╞═══════════╪═══════════╪════════════╡ │ Brasil ┆ Desainer ┆ 275.007296 │ │ Brasil ┆ Guru ┆ 802.384161 │ │ Indonesia ┆ Guru ┆ 848.621492 │ │ Jerman ┆ Polisi ┆ 600.041421 │ │ Jerman ┆ Dokter ┆ 111.512057 │ └───────────┴───────────┴────────────┘
FILTERING
Filtering merupakan proses penyeleksian data yang memenuhi kondisi tertentu.
Mengambil data dimana kolom pekerjaan
adalah "Koder"
:
Python
# PANDAS filt_pd = data_pd[data_pd["pekerjaan"] == "Koder"] # POlARS filt_pl = data_pl.filter(pl.col("pekerjaan") == "Koder") print(filt_pd, f"{'*'*80}", filt_pl, sep="\n\n")
Output
# OUTPUT id asal gender pekerjaan gaji \ 0 XID00000001 Jerman P Koder 110.336394 8 XID00000009 Brasil L Koder 859.190387 11 XID00000012 Amerika Serikat L Koder 1571.616408 12 XID00000013 Brasil P Koder 218.530517 17 XID00000018 Australia L Koder 347.581832 ... ... ... ... ... ... 9999964 XID09999965 Perancis L Koder 157.233492 9999992 XID09999993 Brasil P Koder 2062.169896 9999993 XID09999994 Jepang L Koder 35.178752 9999995 XID09999996 Indonesia L Koder 927.468371 9999997 XID09999998 India P Koder 3748.563698 pengalaman 0 24 8 14 11 19 12 15 17 9 ... ... 9999964 15 9999992 18 9999993 12 9999995 19 9999997 25 [1247517 rows x 6 columns] ******************************************************************************** shape: (1_247_517, 6) ┌─────────────┬─────────────────┬────────┬───────────┬─────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪═════════════════╪════════╪═══════════╪═════════════╪════════════╡ │ XID00000001 ┆ Jerman ┆ P ┆ Koder ┆ 110.336394 ┆ 24 │ │ XID00000009 ┆ Brasil ┆ L ┆ Koder ┆ 859.190387 ┆ 14 │ │ XID00000012 ┆ Amerika Serikat ┆ L ┆ Koder ┆ 1571.616408 ┆ 19 │ │ XID00000013 ┆ Brasil ┆ P ┆ Koder ┆ 218.530517 ┆ 15 │ │ … ┆ … ┆ … ┆ … ┆ … ┆ … │ │ XID09999993 ┆ Brasil ┆ P ┆ Koder ┆ 2062.169896 ┆ 18 │ │ XID09999994 ┆ Jepang ┆ L ┆ Koder ┆ 35.178752 ┆ 12 │ │ XID09999996 ┆ Indonesia ┆ L ┆ Koder ┆ 927.468371 ┆ 19 │ │ XID09999998 ┆ India ┆ P ┆ Koder ┆ 3748.563698 ┆ 25 │ └─────────────┴─────────────────┴────────┴───────────┴─────────────┴────────────┘
Mengambil data dimana kolom pengalaman
lebih dari 10
:
Python
# PANDAS filt_pd = data_pd[data_pd["pengalaman"] < 10] # POLARS filt_pl = data_pl.filter(pl.col("pengalaman") < 10) print(filt_pd, f"{'*'*80}", filt_pl, sep="\n\n")
Output
# OUTPUT id asal gender pekerjaan gaji pengalaman 6 XID00000007 Indonesia L Desainer 1360.856400 0 9 XID00000010 Indonesia L Dokter 1691.490270 0 14 XID00000015 Indonesia L Akuntan 920.104848 9 15 XID00000016 Indonesia L Pilot 64.514460 6 16 XID00000017 Inggris P Dokter 1879.588552 9 ... ... ... ... ... ... ... 9999985 XID09999986 Inggris L Pilot 201.348686 3 9999986 XID09999987 Kanada P Akuntan 297.172377 5 9999988 XID09999989 Jerman P Dokter 485.120648 1 9999989 XID09999990 Australia L Akuntan 2079.732674 1 9999994 XID09999995 Brasil L Akuntan 734.299411 2 [2858720 rows x 6 columns] ******************************************************************************** shape: (2_858_720, 6) ┌─────────────┬───────────┬────────┬───────────┬─────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪═══════════╪════════╪═══════════╪═════════════╪════════════╡ │ XID00000007 ┆ Indonesia ┆ L ┆ Desainer ┆ 1360.8564 ┆ 0 │ │ XID00000010 ┆ Indonesia ┆ L ┆ Dokter ┆ 1691.49027 ┆ 0 │ │ XID00000015 ┆ Indonesia ┆ L ┆ Akuntan ┆ 920.104848 ┆ 9 │ │ XID00000016 ┆ Indonesia ┆ L ┆ Pilot ┆ 64.51446 ┆ 6 │ │ … ┆ … ┆ … ┆ … ┆ … ┆ … │ │ XID09999987 ┆ Kanada ┆ P ┆ Akuntan ┆ 297.172377 ┆ 5 │ │ XID09999989 ┆ Jerman ┆ P ┆ Dokter ┆ 485.120648 ┆ 1 │ │ XID09999990 ┆ Australia ┆ L ┆ Akuntan ┆ 2079.732674 ┆ 1 │ │ XID09999995 ┆ Brasil ┆ L ┆ Akuntan ┆ 734.299411 ┆ 2 │ └─────────────┴───────────┴────────┴───────────┴─────────────┴────────────┘
Filtering dengan beberapa kondisi
Jika kondisi yang diperlukan lebih dari 1, agar menjaga kode tetap mudah dibaca ada baiknya dibuat variabel sendiri untuk menampung kondisi tersebut. Hal ini dapat dilakukan pada pandas
maupun polars
Contoh 1:
Melakukan filter untuk mencari data dimana kolom pekerjaan
diawali dengan huruf P
, serta kolom asal
berisi Indonesia
ataupun India
.
note: abaikan kebermaknaannya 🙂 , filter ini dilakukan untuk memperkaya contoh saja.
Python
# PANDAS cond_pd = data_pd["pekerjaan"].str.startswith("P") & data_pd["asal"].isin( ["Indonesia", "India"] ) filt_pd = data_pd[cond_pd] # POLARS cond_pl = pl.col("pekerjaan").str.starts_with("P") & pl.col("asal").is_in( ["Indonesia", "India"] ) filt_pl = data_pl.filter(cond_pl) print(filt_pd, f"{'*'*80}", filt_pl, sep="\n\n")
Output
# OUTPUT id asal gender pekerjaan gaji pengalaman 15 XID00000016 Indonesia L Pilot 64.514460 6 21 XID00000022 Indonesia L Pengusaha 886.353754 21 37 XID00000038 India L Pengusaha 1767.078989 0 60 XID00000061 India L Pengusaha 482.118390 12 111 XID00000112 India P Pilot 2103.368028 33 ... ... ... ... ... ... ... 9999913 XID09999914 India L Polisi 733.847029 20 9999921 XID09999922 India L Polisi 499.794562 15 9999945 XID09999946 India P Pengusaha 2244.445694 8 9999966 XID09999967 Indonesia L Pengusaha 108.542146 7 9999991 XID09999992 Indonesia P Polisi 1811.172822 29 [749440 rows x 6 columns] ******************************************************************************** shape: (749_440, 6) ┌─────────────┬───────────┬────────┬───────────┬─────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪═══════════╪════════╪═══════════╪═════════════╪════════════╡ │ XID00000016 ┆ Indonesia ┆ L ┆ Pilot ┆ 64.51446 ┆ 6 │ │ XID00000022 ┆ Indonesia ┆ L ┆ Pengusaha ┆ 886.353754 ┆ 21 │ │ XID00000038 ┆ India ┆ L ┆ Pengusaha ┆ 1767.078989 ┆ 0 │ │ XID00000061 ┆ India ┆ L ┆ Pengusaha ┆ 482.11839 ┆ 12 │ │ … ┆ … ┆ … ┆ … ┆ … ┆ … │ │ XID09999922 ┆ India ┆ L ┆ Polisi ┆ 499.794562 ┆ 15 │ │ XID09999946 ┆ India ┆ P ┆ Pengusaha ┆ 2244.445694 ┆ 8 │ │ XID09999967 ┆ Indonesia ┆ L ┆ Pengusaha ┆ 108.542146 ┆ 7 │ │ XID09999992 ┆ Indonesia ┆ P ┆ Polisi ┆ 1811.172822 ┆ 29 │ └─────────────┴───────────┴────────┴───────────┴─────────────┴────────────┘
Contoh 2:
Melakukan filter untuk mencari data dimana kolom gaji
bernilai antara 1000
dan 2500
, serta kolom pengalaman
bernilai tepat 10
.
Python
# PANDAS cond_pd = data_pd["gaji"].between(1000, 2500) & (data_pd["pengalaman"] == 10) filt_pd = data_pd[cond_pd] # POLARS cond_pl = pl.col("gaji").is_between(1000, 2500) & (pl.col("pengalaman") == 10) filt_pl = data_pl.filter(cond_pl) print(filt_pd, f"{'*'*80}", filt_pl, sep="\n\n")
Output
# OUTPUT id asal gender pekerjaan gaji \ 110 XID00000111 Inggris P Pengusaha 1268.389184 139 XID00000140 Inggris P Dokter 1971.490726 163 XID00000164 Kanada P Pengusaha 1820.001603 190 XID00000191 Indonesia P Desainer 1900.547420 589 XID00000590 Australia L Polisi 2024.816388 ... ... ... ... ... ... 9999593 XID09999594 Brasil L Dokter 1657.189880 9999704 XID09999705 Perancis P Pengusaha 2022.726099 9999806 XID09999807 Jepang P Polisi 1785.394270 9999881 XID09999882 Amerika Serikat P Dokter 1515.311444 9999917 XID09999918 Perancis L Pilot 1450.328763 pengalaman 110 10 139 10 163 10 190 10 589 10 ... ... 9999593 10 9999704 10 9999806 10 9999881 10 9999917 10 [81865 rows x 6 columns] ******************************************************************************** shape: (81_865, 6) ┌─────────────┬─────────────────┬────────┬───────────┬─────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪═════════════════╪════════╪═══════════╪═════════════╪════════════╡ │ XID00000111 ┆ Inggris ┆ P ┆ Pengusaha ┆ 1268.389184 ┆ 10 │ │ XID00000140 ┆ Inggris ┆ P ┆ Dokter ┆ 1971.490726 ┆ 10 │ │ XID00000164 ┆ Kanada ┆ P ┆ Pengusaha ┆ 1820.001603 ┆ 10 │ │ XID00000191 ┆ Indonesia ┆ P ┆ Desainer ┆ 1900.54742 ┆ 10 │ │ … ┆ … ┆ … ┆ … ┆ … ┆ … │ │ XID09999705 ┆ Perancis ┆ P ┆ Pengusaha ┆ 2022.726099 ┆ 10 │ │ XID09999807 ┆ Jepang ┆ P ┆ Polisi ┆ 1785.39427 ┆ 10 │ │ XID09999882 ┆ Amerika Serikat ┆ P ┆ Dokter ┆ 1515.311444 ┆ 10 │ │ XID09999918 ┆ Perancis ┆ L ┆ Pilot ┆ 1450.328763 ┆ 10 │ └─────────────┴─────────────────┴────────┴───────────┴─────────────┴────────────┘
Contoh 3:
Membuat filter data dimana kolom asal
bernilai "Indonesia"
atau "India
“, kolom gaji
bernilai lebih besar dari 1000
dan pengalaman
kurang dari 5
.
Python
# PANDAS cond_pd = ( (data_pd["asal"].isin(["Indonesia", "India"])) & (data_pd["gaji"] > 1000) & (data_pd["pengalaman"] < 5) ) filt_pd = data_pd[cond_pd] # POLARS cond_pl = ( pl.col("asal").is_in(["Indonesia", "India"]) & (pl.col("gaji") > 1000) & (pl.col("pengalaman") < 5) ) filt_pl = data_pl.filter(cond_pl) print(filt_pd, f"{'*'*80}", filt_pl, sep="\n\n")
Output
# OUTPUT id asal gender pekerjaan gaji pengalaman 6 XID00000007 Indonesia L Desainer 1360.856400 0 9 XID00000010 Indonesia L Dokter 1691.490270 0 37 XID00000038 India L Pengusaha 1767.078989 0 50 XID00000051 India L Dokter 1604.447364 1 364 XID00000365 India L Akuntan 3414.191380 3 ... ... ... ... ... ... ... 9999614 XID09999615 Indonesia L Guru 1617.190879 2 9999617 XID09999618 India L Guru 1368.415563 1 9999675 XID09999676 India P Desainer 2430.625506 2 9999727 XID09999728 Indonesia L Guru 3616.867661 2 9999812 XID09999813 India P Pengusaha 2169.359820 4 [105170 rows x 6 columns] ******************************************************************************** shape: (105_170, 6) ┌─────────────┬───────────┬────────┬───────────┬─────────────┬────────────┐ │ id ┆ asal ┆ gender ┆ pekerjaan ┆ gaji ┆ pengalaman │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str ┆ str ┆ f64 ┆ i64 │ ╞═════════════╪═══════════╪════════╪═══════════╪═════════════╪════════════╡ │ XID00000007 ┆ Indonesia ┆ L ┆ Desainer ┆ 1360.8564 ┆ 0 │ │ XID00000010 ┆ Indonesia ┆ L ┆ Dokter ┆ 1691.49027 ┆ 0 │ │ XID00000038 ┆ India ┆ L ┆ Pengusaha ┆ 1767.078989 ┆ 0 │ │ XID00000051 ┆ India ┆ L ┆ Dokter ┆ 1604.447364 ┆ 1 │ │ … ┆ … ┆ … ┆ … ┆ … ┆ … │ │ XID09999618 ┆ India ┆ L ┆ Guru ┆ 1368.415563 ┆ 1 │ │ XID09999676 ┆ India ┆ P ┆ Desainer ┆ 2430.625506 ┆ 2 │ │ XID09999728 ┆ Indonesia ┆ L ┆ Guru ┆ 3616.867661 ┆ 2 │ │ XID09999813 ┆ India ┆ P ┆ Pengusaha ┆ 2169.35982 ┆ 4 │ └─────────────┴───────────┴────────┴───────────┴─────────────┴────────────┘
AGGREGATING, GROUPING & SORTING
Agregasi Data
Beberapa fungsi agregasi data sudah tersedia secara default baik pada pandas
maupun polars
seperti menghitung mean
, median
, min
, max
, std
dan sebagainya.
Python
# PANDAS mean_pd = data_pd["gaji"].mean() med_pd = data_pd["gaji"].median() std_pd = data_pd["gaji"].std() print(f"pandas :\n mean : {mean_pd} \n med : {med_pd} \n std : {std_pd}\n") # POLARS mean_pl = data_pl.select("gaji").mean() med_pl = data_pl.select("gaji").median() std_pl = data_pl.select("gaji").std() print(f"polars ; \n mean : {mean_pl} \n med : {med_pl} \n std : {std_pl}")
Output
# OUTPUT pandas : mean : 999.7723122193836 med : 693.0721332725727 std : 999.8239076926443 polars ; mean : shape: (1, 1) ┌────────────┐ │ gaji │ │ --- │ │ f64 │ ╞════════════╡ │ 999.772312 │ └────────────┘ med : shape: (1, 1) ┌────────────┐ │ gaji │ │ --- │ │ f64 │ ╞════════════╡ │ 693.072133 │ └────────────┘ std : shape: (1, 1) ┌────────────┐ │ gaji │ │ --- │ │ f64 │ ╞════════════╡ │ 999.823908 │ └────────────┘
Agregasi dengan Grouping
Pada bagian sebelumnya kita melakukan agregasi secara total dimana menghasilkan 1 nilai tunggal saja. Baik pandas
maupun polars
memiiki kemampuan untuk melakukan agregasi yang dikelompokkan berdasarkan kriteria tertentu.
Secara umum, keduanya menggunakan method groupby
dan agg
atau method agregasi lainnya. Namun terdapat sedikit perbedaan pada parameter yang digunakan.
Menghitung jumlah data menurut kolom asal
dan gender
Pada pandas
kita dapat memasukkan dict
pada method agregat
misalkan dengan key berupa kolom id
dengan value "count"
. Sintaks ini berarti kita melakukan agregasi dengan menghitung jumlah baris berdasarkan id
yang kemudian di group berdasarkan kolom asal
dan gender
.
Proses grouping pandas
akan menghasilkan dataframe baru dengan multi-index, tergantung jumlah group yang dibuat. Jika ingin memperoleh datframe yang flat, maka kita dapat menambahkan method reset_index
.
Adapun pada polars
tidak memiliki multi-index sehingga hasil agregasi akan selalu menghasilkan dataframe flat.
Python
# PANDAS group_pd = data_pd.groupby(["asal", "gender"]).agg({"id": "count"}).reset_index() # POLARS group_pl_1 = data_pl.groupby(["asal", "gender"]).count() # atau group_pl_2 = data_pl.groupby(["asal", "gender"]).agg(pl.col("id").count()) print(group_pd, f"{'*'*80}", group_pl_1, group_pl_2, sep="\n\n")
Output
# OUTPUT asal gender id 0 Amerika Serikat L 500233 1 Amerika Serikat P 501195 2 Australia L 499792 3 Australia P 500196 4 Brasil L 500493 5 Brasil P 498816 6 India L 499599 7 India P 499474 8 Indonesia L 500177 9 Indonesia P 500663 10 Inggris L 499764 11 Inggris P 500585 12 Jepang L 499090 13 Jepang P 500197 14 Jerman L 500491 15 Jerman P 500418 16 Kanada L 499391 17 Kanada P 499390 18 Perancis L 500238 19 Perancis P 499798 ******************************************************************************** shape: (20, 3) ┌───────────┬────────┬────────┐ │ asal ┆ gender ┆ count │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ u32 │ ╞═══════════╪════════╪════════╡ │ Inggris ┆ L ┆ 499764 │ │ Australia ┆ L ┆ 499792 │ │ Inggris ┆ P ┆ 500585 │ │ Brasil ┆ P ┆ 498816 │ │ … ┆ … ┆ … │ │ Indonesia ┆ P ┆ 500663 │ │ Kanada ┆ L ┆ 499391 │ │ Australia ┆ P ┆ 500196 │ │ Brasil ┆ L ┆ 500493 │ └───────────┴────────┴────────┘ shape: (20, 3) ┌─────────────────┬────────┬────────┐ │ asal ┆ gender ┆ id │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ u32 │ ╞═════════════════╪════════╪════════╡ │ Kanada ┆ L ┆ 499391 │ │ Jepang ┆ P ┆ 500197 │ │ Indonesia ┆ L ┆ 500177 │ │ Amerika Serikat ┆ P ┆ 501195 │ │ … ┆ … ┆ … │ │ Jepang ┆ L ┆ 499090 │ │ Amerika Serikat ┆ L ┆ 500233 │ │ Indonesia ┆ P ┆ 500663 │ │ Inggris ┆ L ┆ 499764 │ └─────────────────┴────────┴────────┘
Walaupun output yang diperoleh sedikit berbeda, hal ini hanya masalah urutan saja. Kita bisa menghasilkan urutan data yang sama dengan menerapkan sorting.
Misal kita sort secara ascending menurut kolom asal
selanjutnya kita sort menurut kolom gender
secara descending.
Pada pandas
kita perlu menentukan argumen untuk ascending
sebaliknya polars
kita perlu mengatur argumen untuk descending
. Oleh karena itu argumen yang kita masukkan harus saling bertolak belakang antara pandas
dan polars
agar menghasilkan output yang sama.
Python
# PANDAS group_pd_sort = group_pd.sort_values(by=["asal", "gender"], ascending=[True, False]) # POLARS group_pl_1_sort = group_pl_1.sort(by=["asal", "gender"], descending=[False, True]) # atau group_pl_2_sort = group_pl_2.sort(by=["asal", "gender"], descending=[False, True]) print(group_pd_sort, f"{'*'*80}", group_pl_1_sort, group_pl_2_sort, sep="\n\n")
Output
# OUTPU asal gender id 1 Amerika Serikat P 501195 0 Amerika Serikat L 500233 3 Australia P 500196 2 Australia L 499792 5 Brasil P 498816 4 Brasil L 500493 7 India P 499474 6 India L 499599 9 Indonesia P 500663 8 Indonesia L 500177 11 Inggris P 500585 10 Inggris L 499764 13 Jepang P 500197 12 Jepang L 499090 15 Jerman P 500418 14 Jerman L 500491 17 Kanada P 499390 16 Kanada L 499391 19 Perancis P 499798 18 Perancis L 500238 ******************************************************************************** shape: (20, 3) ┌─────────────────┬────────┬────────┐ │ asal ┆ gender ┆ count │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ u32 │ ╞═════════════════╪════════╪════════╡ │ Amerika Serikat ┆ P ┆ 501195 │ │ Amerika Serikat ┆ L ┆ 500233 │ │ Australia ┆ P ┆ 500196 │ │ Australia ┆ L ┆ 499792 │ │ … ┆ … ┆ … │ │ Kanada ┆ P ┆ 499390 │ │ Kanada ┆ L ┆ 499391 │ │ Perancis ┆ P ┆ 499798 │ │ Perancis ┆ L ┆ 500238 │ └─────────────────┴────────┴────────┘ shape: (20, 3) ┌─────────────────┬────────┬────────┐ │ asal ┆ gender ┆ id │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ u32 │ ╞═════════════════╪════════╪════════╡ │ Amerika Serikat ┆ P ┆ 501195 │ │ Amerika Serikat ┆ L ┆ 500233 │ │ Australia ┆ P ┆ 500196 │ │ Australia ┆ L ┆ 499792 │ │ … ┆ … ┆ … │ │ Kanada ┆ P ┆ 499390 │ │ Kanada ┆ L ┆ 499391 │ │ Perancis ┆ P ┆ 499798 │ │ Perancis ┆ L ┆ 500238 │ └─────────────────┴────────┴────────┘
Menghitung rata-rata kolom gaji
menurut kolom asal
Sintaks berikut digunakan untuk menghitung rata-rata gaji
yang dikelompokkan berdasarkan kolom asal
, serta kita lakukan sorting kolom gaji
secara default (ascending).
Python
# PANDAS group_pd = ( data_pd.groupby(["asal"]).agg({"gaji": "mean"}).reset_index().sort_values("gaji") ) # POlARS group_pl = data_pl.groupby(["asal"]).agg(pl.col("gaji").mean()).sort("gaji") print(group_pd, f"{'*'*80}", group_pl, sep="\n\n")
Output
# OUTPUT asal gaji 9 Perancis 998.666696 4 Indonesia 998.831929 7 Jerman 998.849930 0 Amerika Serikat 999.286247 8 Kanada 999.431082 2 Brasil 999.694774 5 Inggris 999.880728 3 India 999.949138 6 Jepang 1000.977000 1 Australia 1002.158505 ******************************************************************************** shape: (10, 2) ┌─────────────────┬─────────────┐ │ asal ┆ gaji │ │ --- ┆ --- │ │ str ┆ f64 │ ╞═════════════════╪═════════════╡ │ Perancis ┆ 998.666696 │ │ Indonesia ┆ 998.831929 │ │ Jerman ┆ 998.84993 │ │ Amerika Serikat ┆ 999.286247 │ │ … ┆ … │ │ Inggris ┆ 999.880728 │ │ India ┆ 999.949138 │ │ Jepang ┆ 1000.977 │ │ Australia ┆ 1002.158505 │ └─────────────────┴─────────────┘
Contoh agregasi yang lebih kompleks
Pada bagian ini kita akan melakukan agregasi, dimana akan hitung gaji
minimal, rata-rata dan maksimal yang dikelompokkan menurut pekerjaan
dan gender
, juga ditambahkan jumlah data (count) pada masing-masing grup. Selanjutnya data diurutkan menurut rata-rata gaji
dari yang tertinggi hingga terendah.
Pada pandas
, karena kita membuat beberapa nilai agregat (min
, mean
, max
) dari 1 kolom (gaji
), maka data frame yang dihasilkan akan memiliki kolom yangg bertingkat. Untuk mengakses kolom yang tepat kita menggunakan tupple. Pada contoh ini adalah ("gaji", "mean")
artinya kolom gaji
dan sub-kolom mean
.
Sementara itu implementasi pada polars
tetap menghasilkan dataframe flat. Kita dapat menentukansecara kustom nama kolom untuk setiap hasil agregasi. pada contoh ini kolom yang akan dihasilkan adalah "id"
, "gaji_min"
, "gaji_mean"
dan "gaji_max"
.
Python
# PANDAS group_pd = ( data_pd.groupby(["pekerjaan", "gender"]) .agg( { "id": "count", "gaji": ["min", "mean", "max"], } ) .reset_index() .sort_values(("gaji", "mean"), ascending=False) ) # POLARS group_pl = ( data_pl.groupby(["pekerjaan", "gender"]) .agg( pl.count("id"), pl.min("gaji").suffix("_min"), pl.mean("gaji").suffix("_mean"), pl.max("gaji").suffix("_max"), ) .sort(["gaji_mean"], descending=True) ) print(group_pd, f"{'*'*80}", group_pl, sep="\n\n")
Output
pekerjaan gender id gaji count min mean max 12 Pilot L 624578 0.000055 1002.709488 14610.014209 7 Guru P 623169 0.002719 1001.879132 12872.188019 0 Akuntan L 624868 0.001105 1001.841321 13312.079775 13 Pilot P 625261 0.001957 1001.068719 14294.444239 6 Guru L 625059 0.002716 1000.753455 12134.925551 2 Desainer L 625694 0.002755 1000.719260 13262.868221 8 Koder L 623521 0.001541 999.988500 13641.082840 4 Dokter L 624825 0.003854 999.898590 12431.508286 11 Pengusaha P 624897 0.003450 999.891025 13776.699447 15 Polisi P 625548 0.000400 999.251016 13779.190591 14 Polisi L 625107 0.001540 998.968230 14399.129384 5 Dokter P 626615 0.003524 998.928506 16787.583138 3 Desainer P 626416 0.002051 998.782463 14485.569934 10 Pengusaha L 625616 0.000547 997.972989 14204.813192 1 Akuntan P 624830 0.000900 997.810545 13052.995696 9 Koder P 623996 0.001234 995.901269 13908.094009 ******************************************************************************** shape: (16, 6) ┌───────────┬────────┬────────┬──────────┬─────────────┬──────────────┐ │ pekerjaan ┆ gender ┆ id ┆ gaji_min ┆ gaji_mean ┆ gaji_max │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ u32 ┆ f64 ┆ f64 ┆ f64 │ ╞═══════════╪════════╪════════╪══════════╪═════════════╪══════════════╡ │ Pilot ┆ L ┆ 624578 ┆ 0.000055 ┆ 1002.709488 ┆ 14610.014209 │ │ Guru ┆ P ┆ 623169 ┆ 0.002719 ┆ 1001.879132 ┆ 12872.188019 │ │ Akuntan ┆ L ┆ 624868 ┆ 0.001105 ┆ 1001.841321 ┆ 13312.079775 │ │ Pilot ┆ P ┆ 625261 ┆ 0.001957 ┆ 1001.068719 ┆ 14294.444239 │ │ … ┆ … ┆ … ┆ … ┆ … ┆ … │ │ Desainer ┆ P ┆ 626416 ┆ 0.002051 ┆ 998.782463 ┆ 14485.569934 │ │ Pengusaha ┆ L ┆ 625616 ┆ 0.000547 ┆ 997.972989 ┆ 14204.813192 │ │ Akuntan ┆ P ┆ 624830 ┆ 0.0009 ┆ 997.810545 ┆ 13052.995696 │ │ Koder ┆ P ┆ 623996 ┆ 0.001234 ┆ 995.901269 ┆ 13908.094009 │ └───────────┴────────┴────────┴──────────┴─────────────┴──────────────┘
MENYIMPAN DATA
pandas
dan polars
memili method untuk menyimpan data hasil pengolahan ke dalam perbagai format. beberapa format yang banyak digunakan yaitu csv, xlsx, json, pickle, feather, parquet, dan sebagainya. parquet merupakan salah satu format yang sangat populer karena mampu mereduksi ukuran file secara signifikan.
Misalkan kita akan menyimpan data awal kita ke dalam format parquet, maka dapat dilakukan menggunakan method to_parquet
pada pandas
atau method write_parquet
pada polars
.
File parquet yang dihasilkan memiliki ukuran hanya sekitar 100MB saja dibandingkan file dalam format CSV yang memiliki ukuran sekitar 500MB.
Setelah file disimpan, kita dapat membukanya lagi menggunakan method read_parquet
atau read_parquet
. Proses pembacaannya pun jauh lebih cepat dibandingkan membaca file CSV.
Python
# exstensinya bebas (misal .pq) # PANDAS data_pd.to_parquet("fake_data_by_pd.pq") # POLARS data_pl.write_parquet("fake_data_by_pl.pq")
Python
# membaca file parquet dengan pandas my_data_1 = pd.read_parquet("fake_data_by_pd.pq") print(my_data_1.info()) # membaca file parquet dengan polars my_data_2 = pl.read_parquet("fake_data_by_pl.pq") print(my_data_2.glimpse())
Output
# OUTPUT <class 'pandas.core.frame.DataFrame'> RangeIndex: 10000000 entries, 0 to 9999999 Data columns (total 6 columns): # Column Dtype --- ------ ----- 0 id object 1 asal object 2 gender object 3 pekerjaan object 4 gaji float64 5 pengalaman int64 dtypes: float64(1), int64(1), object(4) memory usage: 457.8+ MB None ===================================================================== Rows: 10000000 Columns: 6 $ id <str> XID00000001, XID00000002, XID00000003, XID00000004, ... $ asal <str> Jerman, Brasil, Perancis, Jerman, Perancis, Inggris, ... $ gender <str> P, L, L, L, L, P, L, P, L, L $ pekerjaan <str> Koder, Akuntan, Akuntan, Guru, Dokter, Dokter, ... $ gaji <f64> 110.33639368940689, 1063.8895772881397, ... $ pengalaman <i64> 24, 16, 23, 28, 22, 19, 0, 24, 14, 0
RINGKASAN
Meskipun polars
belum sepopuler pandas
, pustaka ini terus berkembang dan menarik minat pengguna yang menginginkan kinerja tinggi dan skalabilitas pada pemrosesan data. Pilihan antara pandas
dan polars
tergantung pada kebutuhan serta skenario yang diperlukan. Jika kita bekerja dengan dataset kecil hingga menengah dan mengutamakan kemudahan penggunaan dan fleksibilitas, pandas
adalah pilihan yang solid. Namun, jika memerlukan pengolahan dataset yang sangat besar dan kinerja tinggi, maka polars
dapat menjadi alternatif karena memberikan keuntungan dalam hal kecepatan dan efisiensi.
Selain itu, ketika kita bekerja dengan polars
, data yang dihasilkan dapat disimpan menjadi objek dataframe pandas
. Dengan kemampuan ini, maka kita dapat melakukan berbagai proses penggunakan polars
kemudian untuk bagian lainnya (misal visualisasi) yang belum tercakup oleh polars
dapat kita lakukan melalui pandas
, ataupun pustaka lainnya.
Apa yang disampaikan pada tutorial ini baru sebagian kecil saja dari fitur yang tersedia pada pandas
dan polars
. Untuk memahami selengkap mungkin silahkan melihat dokumentasi dari kedua pustaka tersebut.
pandas
docs : https://pandas.pydata.org/docs/
polars
docs : https://pola-rs.github.io/polars/py-polars/html/reference/