pandas 2.2.3 — versi yang kami pakai untuk menguji bab ini — dibangun di atas NumPy: di balik setiap kolom DataFrame terdapat array NumPy yang diberi label. Karena keduanya serumpun, pertukaran data antara DataFrame/Series dan ndarray hampir tanpa gesekan. Persoalan menarik justru ada pada detailnya: dtype apa yang muncul setelah konversi, dan konversi mana yang menyalin data.

Kita mulai dari arah NumPy ke pandas, lalu kembali ke NumPy dengan to_numpy(), dan ditutup dengan aturan salin-tempel memori (copy=True) yang sering menyelamatkan dari bug halus.

Membangun DataFrame dari Array NumPy #

Konstruktor pd.DataFrame menempatkan kolom array berdasarkan posisi, lalu melabelinya dengan columns dan index:

python
import numpy as np
import pandas as pd

data = np.array([
    [3500, 120],
    [5000, 80],
    [12000, 25],
])
df = pd.DataFrame(data, columns=["harga", "stok"],
                  index=["Indomie", "Teh Kotak", "Kopi Sachet"])
print(df)
df["nilai"] = data[:, 0] * data[:, 1]
print(df)

Output yang Dihasilkan:

text
             harga  stok
Indomie       3500   120
Teh Kotak     5000    80
Kopi Sachet  12000    25
             harga  stok   nilai
Indomie       3500   120  420000
Teh Kotak     5000    80  400000
Kopi Sachet  12000    25  300000

Bedah baris demi baris:

  1. Baris 4-8: array data berbentuk (3, 2) bertipe int64 — stok gudang tiga produk fiktif.
  2. Baris 9-10 (pd.DataFrame(data, ...)): kolom ke-0 menjadi harga dan kolom ke-1 menjadi stok semata karena urutannya; label index tidak menyaring atau menata ulang baris, array mentah tidak mengenal label.
  3. Baris 11-12: kolom baru nilai dihitung dengan vectorization di array (data[:, 0] * data[:, 1]) sebelum diserahkan ke pandas; panjang hasilnya harus cocok dengan jumlah baris.

Dua istilah yang perlu dibedakan: index adalah label baris milik pandas, sedangkan ndarray hanya bekerja secara posisional. Bila data kita berpindah dari array ke DataFrame, penugasan label terjadi setelah data tersalin, bukan saat penghitungan.

Mengubah DataFrame Menjadi Array #

df.to_numpy() adalah cara yang disarankan untuk keluar dari DataFrame ke ndarray. Bentuk dan nilainya mengikuti semua kolom, sedangkan dtype menyesuaikan isi kolom terburuk:

python
import numpy as np
import pandas as pd

df = pd.DataFrame({
    "produk": ["Indomie", "Teh Kotak"],
    "harga": [3500, 5000],
    "stok": [120, 80],
})
arr = df.to_numpy()
print(arr)
print(arr.dtype)

Output yang Dihasilkan:

text
[['Indomie' 3500 120]
 ['Teh Kotak' 5000 80]]
object

Penjelasannya:

  1. Baris 3-8: DataFrame berisi satu kolom teks dan dua kolom numerik.
  2. Baris 9-11 (df.to_numpy()): hasilnya array 2-D berisi semua kolom; karena satu DataFrame harus satu dtype, kehadiran kolom teks memaksa seluruh array menjadi object.
  3. Baris 12 (print(arr.dtype)): dtype object berarti setiap sel adalah objek Python terpisah — semua keunggulan kecepatan NumPy hilang pada array ini.

Series dan Array Dua Arah #

Untuk satu kolom, Series bertukar data dengan array 1-D tanpa banyak drama. Yang perlu diingat: label index tidak ikut pindah ke array, sehingga kita harus menyerahkannya kembali secara eksplisit:

python
import numpy as np
import pandas as pd

s = pd.Series([27.5, 28.1, 26.9], index=["Senin", "Selasa", "Rabu"])
a = s.to_numpy()
print(a, a.dtype)
print("rata-rata:", np.mean(a))
kembali = pd.Series(a, index=s.index)
print(kembali)

Output yang Dihasilkan:

text
[27.5 28.1 26.9] float64
rata-rata: 27.5
Senin     27.5
Selasa    28.1
Rabu      26.9
dtype: float64

Bedah singkat:

  1. Baris 3-5: s.to_numpy() menghasilkan ndarray float64; label Senin/Selasa/Rabu tinggal di pandas, array hanya membawa nilai.
  2. Baris 6: fungsi NumPy seperti np.mean langsung menerima hasilnya — di sinilah NumPy menjadi bahasa bersama antar pustaka.
  3. Baris 7-8: konstruktor pd.Series(a, index=s.index) menyusun kembali Series; nilai ditempatkan berdasarkan posisi, lalu label index lama ditempelkan pada posisi tersebut.

Aturan Salin Memori: to_numpy(copy=True) #

Bagian ini adalah gotcha terpenting bab. Secara bawaan, to_numpy() boleh mengembalikan array yang berbagi memori dengan kolom DataFrame; mutasi array akan merembes ke DataFrame:

python
import numpy as np
import pandas as pd

df = pd.DataFrame({"suhu": [27.5, 28.1, 26.9]})
arr = df.to_numpy()
print("default berbagi ->", np.shares_memory(arr, df["suhu"].to_numpy()))
arr[0, 0] = 99.0
print("df ikut berubah ->", df["suhu"].iloc[0])
arr2 = df.to_numpy(copy=True)
arr2[0, 0] = 5.0
print("df dgn copy=True ->", df["suhu"].iloc[0])

Output yang Dihasilkan:

text
default berbagi -> True
df ikut berubah -> 99.0
df dgn copy=True -> 99.0

Mari kita baca hasilnya:

  1. Baris 5-6: pada DataFrame satu-dtype seperti ini, to_numpy() mengembalikan array yang berbagi buffer dengan kolom suhu — np.shares_memory membuktikan True.
  2. Baris 7-8: menulisi arr[0, 0] langsung mengubah nilai di dalam DataFrame; dua objek berbeda, satu memori.
  3. Baris 9-11: copy=True memaksa salinan baru; perubahan arr2 tidak memengaruhi df sama sekali (nilainya tetap 99.0 dari mutasi sebelumnya).

Ringkasan Arah Konversi #

KebutuhanAPICatatan
Array ke DataFramepd.DataFrame(arr, columns=..., index=...)kolom ditempatkan berdasarkan posisi
DataFrame ke arraydf.to_numpy()dtype mengikuti gabungan kolom; bisa object
Series ke arrays.to_numpy()index tidak ikut; nilai saja
Array ke Seriespd.Series(a, index=...)nilai posisional, label ditempel
Salin terjamindf.to_numpy(copy=True)wajib bila array akan dimutasi

Dengan lima pola di atas, hampir semua kebutuhan harian NumPy–pandas terselesaikan. Untuk data yang mengandung nilai kosong, ingat bahwa pandas menandainya sebagai NaN — perlakuannya dibahas pada bab NaN dan Infinity, sementara persamaan dan perbedaan kedua pustaka ini terasa paling jelas ketika kita membaca kembali Pengenalan Vectorization.