Pengolahan Data dangan Python : Pandas vs Polars

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          │
└─────────────┴────────┴────────┴───────────┴────────────┴────────────┘

Slicing Data Menurut Baris dan Kolom

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/

Tulisan Lainnya

You may also like...

Leave a Reply

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

Daftar Isi