Ketika kita memanggil df.sum() atau mengalikan dua kolom DataFrame, sebenarnya pandas sedang memanggil mesin NumPy di balik layar. NumPy menyediakan struktur array berkecepatan tinggi yang menjadi fondasi hampir semua library data di Python, dan pandas membungkus fondasi itu dengan index serta label kolom yang nyaman digunakan. Memahami relasi keduanya membuat kita tahu kapan harus tetap di pandas dan kapan perlu turun ke array NumPy. Pada Chapter ini kita membedah kedudukan NumPy di dalam pandas, lalu berlatih pertukaran data dua arah antara DataFrame dan ndarray.

NumPy sebagai Fondasi pandas #

NumPy (Numerical Python) menyediakan ndarray, yaitu array berdimensi-N yang isinya disimpan berdampingan di memori. Karena data tersimpan rapat, operasi aritmetika NumPy berjalan vectorized: satu perintah memproses seluruh elemen dalam kode C, jauh lebih cepat daripada loop Python.

pandas tidak menemukan kembali mesin itu. Setiap kolom Series menyimpan nilainya dalam satu ndarray, dan DataFrame mengelola kumpulan blok kolom tersebut sambil menambahkan dua hal yang tidak dimiliki NumPy murni: index berlabel dan kolom bernama. Tabel berikut merangkum pembagian peran keduanya.

AspekNumPypandas
Strukturndarray berdimensi-NSeries dan DataFrame
Penandaanposisi angka saja (0, 1, 2, …)index dan nama kolom yang bisa dinamai
Tipe data campuransatu dtype untuk semua elementiap kolom boleh punya dtype sendiri
Peranmesin komputasi arraypengelola data tabel berlabel

Membangun DataFrame dari ndarray #

Arah pertukaran pertama: ndarray menjadi DataFrame. Kita memberikan array dua dimensi beserta daftar index dan columns.

python
import numpy as np
import pandas as pd

# 1. Membangun DataFrame dari ndarray NumPy
data = np.array([
    [40, 68000],
    [25, 35000],
    [30, 18000],
])
penjualan = pd.DataFrame(
    data, index=["Beras", "Minyak", "Gula"], columns=["jumlah", "harga"]
)
print(penjualan)
print()

# 2. Kembali ke ndarray dengan to_numpy()
arr = penjualan.to_numpy()
print("tipe arr  :", type(arr).__name__)
print("dtype arr :", arr.dtype)
print("writeable :", arr.flags.writeable)
print()

# 3. Fungsi NumPy pada Series mengembalikan Series
log_jumlah = np.log1p(penjualan["jumlah"])
print("np.log1p(Series) ->", type(log_jumlah).__name__)
print(log_jumlah.round(3))
print()

# 4. np.where menghasilkan ndarray murni
label = np.where(penjualan["jumlah"] >= 30, "banyak", "sedang")
print("np.where ->", type(label).__name__, label.tolist())
print()

# 5. Hasil ndarray bisa menjadi kolom baru
penjualan["total"] = penjualan["jumlah"].to_numpy() * penjualan["harga"].to_numpy()
print(penjualan)

Output yang Dihasilkan:

text
        jumlah  harga
Beras       40  68000
Minyak      25  35000
Gula        30  18000

tipe arr  : ndarray
dtype arr : int64
writeable : False

np.log1p(Series) -> Series
Beras     3.714
Minyak    3.258
Gula      3.434
Name: jumlah, dtype: float64

np.where -> ndarray ['banyak', 'sedang', 'banyak']

        jumlah  harga    total
Beras       40  68000  2720000
Minyak      25  35000   875000
Gula        30  18000   540000

Mari kita telaah baris-baris pentingnya:

  1. Baris 5-9 (data = np.array([...])): NumPy membangun array dua dimensi bertipe int64 berisi tiga baris dan dua kolom. Array ini masih “buta” terhadap makna datanya.
  2. Baris 10-12 (pd.DataFrame(data, index=..., columns=...)): pandas membungkus array tersebut menjadi tabel berlabel; barisnya bernama Beras, Minyak, Gula dan kolomnya bernama jumlah, harga.
  3. Baris 17-20 (arr = penjualan.to_numpy()): method to_numpy() mengembalikan kembali isi tabel sebagai ndarray. Perhatikan writeable: False — array hasil konversi bersifat read-only; kita akan membahas alasannya pada bagian berikutnya.
  4. Baris 24-26 (np.log1p(penjualan["jumlah"])): fungsi NumPy yang menerima Series mengembalikan Series lagi, lengkap dengan index Beras, Minyak, Gula. pandas memastikan fungsi NumPy tidak membuang label.
  5. Baris 30-31 (np.where(...)): fungsi np.where() bekerja di level array sehingga hasilnya ndarray murni tanpa index, lalu label.tolist() mengubahnya menjadi list Python.
  6. Baris 35 (penjualan["total"] = ...): hasil perkalian dua ndarray menjadi kolom baru; pertukaran array-ke-pandas berlangsung dalam satu baris.

Fungsi NumPy yang Sadar-DataFrame #

Pola pada baris 24 dan 30 menunjukkan dua perilaku berbeda yang perlu kita pegang. Fungsi NumPy yang diteruskan pandas — seperti np.log1p, np.sqrt, dan np.abs — menghormati struktur pandas: masukan Series menghasilkan Series, dan masukan DataFrame menghasilkan DataFrame. Nama index dan kolom ikut terbawa, sehingga hasilnya bisa langsung dipakai kembali dalam alur kerja tabel.

Sebaliknya, fungsi yang bekerja di level array seperti np.where() atau np.asarray() mengembalikan ndarray tanpa label. Hasil tersebut cocok untuk dikonsumsi kode NumPy lain, tetapi tidak lagi bisa memanfaatkan fitur seleksi berlabel pandas.

Kapan Turun ke Array NumPy #

Kita tetap di pandas selama pekerjaannya berkaitan dengan tabel: seleksi berlabel, penggabungan, agregasi, dan pembersihan data. Kita turun ke ndarray ketika kebutuhannya milik NumPy: operasi aljabar linear lewat arr @ vektor, fungsi ilmiah yang hanya ada di NumPy, atau antarmuka ke library yang menuntut array murni sebagai input. Baris 35 pada contoh di atas memperlihatkan jalan tengahnya — hitung di level array, simpan kembali sebagai kolom DataFrame.

Setelah fondasi ini jelas, babak berikutnya menambahkan lapisan visual: pandas menyediakan method .plot() yang mendelegasikan seluruh penggambarannya ke Matplotlib, dan itulah topik Chapter berikutnya.

Referensi resmi yang relevan untuk chapter ini: dokumentasi NumPy , pandas.DataFrame.to_numpy , dan catatan rilis pandas 3.0.0 yang menjelaskan perubahan Copy-on-Write.