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 sajaOutput
# 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/





