Traffine I/O

Bahasa Indonesia

2022-11-15

Teknik untuk Meningkatkan Performa dan Efisiensi Pandas

Pendahuluan

Pandas adalah pustaka Python yang sangat baik untuk manipulasi dan analisis data, menyediakan struktur data dan fungsi yang diperlukan untuk bekerja dengan data terstruktur. Meskipun Pandas dikenal karena fleksibilitas dan kemudahannya dalam penggunaan, namun dapat mengalami masalah performa saat menangani dataset yang besar. Untuk mengatasi keterbatasan ini, penting untuk memahami dan menerapkan teknik optimisasi pada alur kerja Pandas Anda.

Pengambilan Data yang Efisien

Pengambilan data yang efisien merupakan aspek penting dalam mengoptimalkan alur kerja Pandas. Untuk mengoptimalkan performa, pengguna harus dengan cermat memilih jenis data untuk setiap kolom, mengelola penggunaan memori, dan, jika perlu, menggunakan chunking dan iterasi untuk memproses data dalam bagian yang lebih kecil.

Jenis Data dan Manajemen Memori

Saat memuat data, Pandas secara otomatis menyimpulkan jenis data untuk setiap kolom berdasarkan data input. Namun, proses ini terkadang dapat menghasilkan hasil yang suboptimal, seperti memuat kolom yang berisi bilangan bulat sebagai float64 dtype, yang mengonsumsi lebih banyak memori.

Untuk mengoptimalkan penggunaan memori dan meningkatkan performa, Anda dapat secara eksplisit menentukan jenis data untuk setiap kolom dengan menggunakan parameter dtype saat membaca data.

python
import pandas as pd

# Menentukan jenis data untuk setiap kolom
data = pd.read_csv('data.csv', dtype={'column1': 'int32', 'column2': 'category'})

Chunking dan Iterasi

Ketika bekerja dengan dataset yang besar, memuat seluruh data ke dalam memori mungkin tidak layak. Dalam kasus seperti ini, Anda dapat menggunakan parameter chunksize untuk memproses data dalam bagian yang lebih kecil atau "chunk". Pendekatan ini memungkinkan Anda untuk mengiterasi dataset dan melakukan operasi pada setiap chunk secara terpisah, mengurangi jejak memori.

python
import pandas as pd

# Membaca data dalam chunk
chunk_size = 1000
data_reader = pd.read_csv('large_data.csv', chunksize=chunk_size)

for chunk in data_reader:
    # Melakukan operasi pada setiap chunk
    print(chunk.head())

Dengan memproses data dalam chunk yang lebih kecil, Anda dapat melakukan operasi pada dataset yang besar tanpa kehabisan memori. Namun, penting untuk diingat bahwa beberapa operasi, seperti pengurutan dan pengelompokan, mungkin memerlukan langkah atau teknik tambahan untuk memproses data secara efisien dalam chunk.

Peningkatan Performa

Peningkatan performa dapat dicapai melalui vektorisasi, yang melibatkan melakukan operasi pada seluruh array daripada secara berurutan. Metode ini memanfaatkan optimasi tingkat rendah dan menghindari overhead dari loop Python. Selain vektorisasi, pengguna dapat memanfaatkan fungsi NumPy dan metode bawaan Pandas, seperti method chaining, untuk meningkatkan performa.

Vektorisasi

Vektorisasi merujuk pada praktik melakukan operasi pada seluruh array atau struktur data, bukan melalui iterasi elemen satu per satu. Teknik ini memungkinkan Pandas untuk memanfaatkan optimasi tingkat rendah, termasuk optimasi yang disediakan oleh pustaka NumPy yang mendasari, untuk mencapai kinerja yang jauh lebih baik.

Dalam Pandas, operasi vektorisasi dapat dilakukan dengan menggunakan fungsi dan metode bawaan yang disediakan untuk objek Series dan DataFrame. Operasi ini meliputi operasi aritmatika, perbandingan, dan logika.

python
import pandas as pd

data = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
result = data * 2  # Perkalian vektorisasi

Menggunakan Fungsi NumPy

NumPy adalah pustaka yang kuat untuk komputasi numerik dalam Python dan merupakan dasar bagi Pandas. Dengan memanfaatkan fungsi NumPy, dapat meningkatkan performa operasi Pandas. Banyak fungsi NumPy yang kompatibel dengan objek Series dan DataFrame Pandas, memungkinkan integrasi yang mulus antara dua pustaka.

python
import numpy as np
import pandas as pd

data = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
result = np.sqrt(data)  # Menerapkan fungsi akar kuadrat pada setiap elemen

Data Kategoris

Data kategoris, seperti string atau faktor, dapat disimpan dan dimanipulasi secara efisien menggunakan tipe data Categorical Pandas. Tipe data Categorical menyimpan data sebagai bilangan bulat dengan pemetaan nilai bilangan bulat yang terpisah ke label kategori, yang dapat secara signifikan mengurangi penggunaan memori dan meningkatkan performa, terutama untuk operasi seperti pengurutan, pengelompokan, dan penggabungan.

python
import pandas as pd

data = pd.Series(['apple', 'banana', 'apple', 'orange'], dtype='category')

Method Chaining

Method chaining adalah teknik pemrograman yang kuat yang memungkinkan Anda melakukan beberapa operasi pada struktur data dalam satu pernyataan yang singkat dan ringkas. Dalam Pandas, banyak metode DataFrame dan Series mengembalikan objek baru, yang dapat dimodifikasi atau diubah dengan panggilan metode tambahan.

Dengan menggunakan method chaining, dapat mengurangi jumlah variabel perantara dalam kode Anda, membuatnya lebih mudah dibaca dan efisien. Teknik ini juga dapat meningkatkan performa dengan mengurangi kebutuhan untuk membuat beberapa objek sementara selama pengolahan data Anda.

python
import pandas as pd

data = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})

result = (
    data.assign(C=lambda df: df['A'] * 2)
    .query('C > 3')
    .sort_values(by='C', ascending=False)
)

Dalam contoh ini, kita membuat kolom baru 'C', menyaring baris yang memiliki nilai 'C' lebih besar dari 3, dan mengurutkan baris yang tersisa berdasarkan kolom 'C' secara menurun, semuanya dalam satu pernyataan.

Pemrosesan Paralel

Pemrosesan paralel dapat secara signifikan meningkatkan performa saat bekerja dengan dataset besar. Pustaka seperti Dask dan Swifter dapat digunakan untuk memparalelkan operasi Pandas, sedangkan modul multiprocessing di pustaka standar Python juga dapat digunakan untuk mendistribusikan beban kerja di beberapa proses.

Menggunakan Dask untuk Pemrosesan Paralel

Dask adalah pustaka komputasi paralel yang fleksibel untuk Python yang dapat digunakan untuk memparalelkan operasi Pandas. Dask menyediakan Dask DataFrame, yang merupakan DataFrame paralel besar yang terdiri dari DataFrame Pandas yang lebih kecil, dibagi menjadi indeks. Dask DataFrame meniru API Pandas, sehingga mudah untuk memperbesar alur kerja Pandas Anda ke dataset yang lebih besar.

python
import dask.dataframe as dd

# Read data into a Dask DataFrame
dask_data = dd.read_csv('large_data.csv')

# Perform operations on the Dask DataFrame
result = dask_data.groupby('column1').mean()

# Compute the result and return a Pandas DataFrame
result_pd = result.compute()

Menggunakan Swifter untuk Operasi Dipercepat

Swifter adalah pustaka yang bertujuan untuk secara efisien menerapkan fungsi apa pun yang diberikan ke DataFrame atau Series Pandas. Ini dicapai dengan secara otomatis memilih strategi optimal, baik vektorisasi atau pemrosesan paralel dengan Dask, berdasarkan data dan fungsi masukan. Swifter dapat signifikan meningkatkan performa operasi yang tidak secara alami divektorisasi di Pandas, seperti fungsi khusus yang diterapkan menggunakan metode apply.

python
import pandas as pd
import swifter

data = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})

# Mendefinisikan fungsi khusus untuk mengkuadratkan nilai masukan
def square(x):
    return x**2

# Menerapkan fungsi khusus menggunakan Swifter
data['C'] = data['A'].swifter.apply(square)

Multiprocessing dengan Pandas

Pustaka standar Python, yaitu modul multiprocessing, dapat digunakan untuk memparalelkan operasi Pandas dengan mendistribusikan beban kerja di beberapa proses. Pendekatan ini dapat sangat berguna untuk tugas yang membutuhkan banyak komputasi, seperti menerapkan fungsi khusus pada dataset besar.

python
import pandas as pd
from multiprocessing import Pool, cpu_count

data = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})

# Mendefinisikan fungsi khusus untuk mengkuadratkan nilai masukan
def square(x):
    return x**2

# Memecah data menjadi beberapa bagian untuk pemrosesan paralel
num_partitions = cpu_count()  # Jumlah core CPU
num_cores = cpu_count()
data_split = np.array_split(data, num_partitions)

# Define a function to apply the custom function to each chunk
def process_data(data_chunk):
    return data_chunk['A'].apply(square)

# Paralelkan operasi menggunakan multiprocessing
with Pool(num_cores) as pool:
    results = pool.map(process_data, data_split)

# Menggabungkan hasil menjadi satu DataFrame Pandas
data['C'] = pd.concat(results)

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!