1. Pengenalan NumPy
NumPy (Numerical Python) adalah library fundamental untuk komputasi numerik di Python. NumPy menyediakan objek array multidimensi yang cepat dan efisien, serta berbagai fungsi matematika untuk operasi pada array tersebut.
NumPy menjadi fondasi bagi hampir semua library data science di Python, termasuk Pandas, Matplotlib, Scikit-learn, TensorFlow, dan PyTorch. Tanpa NumPy, ekosistem data science Python tidak akan sekuat saat ini.
Mengapa Menggunakan NumPy?
| Keunggulan | Penjelasan |
|---|---|
| Kecepatan | Operasi NumPy 10-100x lebih cepat dari loop Python biasa karena ditulis dalam C |
| Memori Efisien | Menyimpan data lebih kompak dibanding list Python |
| Vektorisasi | Operasi pada seluruh array tanpa perlu loop eksplisit |
| Broadcasting | Operasi antar array dengan ukuran berbeda secara otomatis |
| Linear Algebra | Fungsi lengkap untuk aljabar linear, transformasi, dan dekomposisi |
| Ekosistem | Menjadi dasar bagi Pandas, Matplotlib, Scikit-learn, dan banyak lagi |
NumPy List vs Python List
┌─────────────────────────────────────────────────────────┐ │ PYTHON LIST │ NUMPY ARRAY │ │ │ │ │ [1, "dua", 3.0, True] │ [1, 2, 3, 4, 5] │ │ ▪ Tipe campuran │ ▪ Tipe seragam │ │ ▪ Fleksibel tapi lambat │ ▪ Kaku tapi cepat │ │ ▪ Pointer-based (boros RAM) │ ▪ Contiguous memory │ │ ▪ Loop manual untuk operasi │ ▪ Operasi vektorisasi │ │ │ │ │ [1,2,3] + [4,5,6] │ [1,2,3] + [4,5,6] │ │ = [1,2,3,4,5,6] (gabung) │ = [5,7,9] (elemen) │ └─────────────────────────────────────────────────────────┘
2. Instalasi NumPy
NumPy bisa diinstal dengan mudah menggunakan pip atau conda.
Instalasi dengan pip
# Instal NumPy dengan pip pip install numpy # Instal versi spesifik pip install numpy==1.26.4 # Upgrade ke versi terbaru pip install --upgrade numpy # Verifikasi instalasi python -c "import numpy; print(numpy.__version__)" # Output: 1.26.4
Instalasi dengan conda
# Instal NumPy dengan conda (Anaconda/Miniconda) conda install numpy # Instal di environment tertentu conda create -n datasci python=3.12 numpy pandas matplotlib conda activate datasci
Import NumPy
# Konvensi import NumPy — selalu gunakan alias 'np' import numpy as np # Cek versi print(np.__version__) # 1.26.4 # Cek konfigurasi print(np.show_config())
Selalu gunakan import numpy as np — ini adalah konvensi universal yang diikuti oleh seluruh komunitas data science. Menulis np.array() lebih ringkas daripada numpy.array().
3. Membuat Array
NumPy menyediakan berbagai cara untuk membuat array — dari list Python, dengan nilai konstanta, dengan deret angka, atau dengan distribusi random.
Array dari List Python
import numpy as np
# Array 1D dari list
arr1d = np.array([1, 2, 3, 4, 5])
print(arr1d) # [1 2 3 4 5]
print(type(arr1d)) # <class 'numpy.ndarray'>
# Array 2D (matriks) dari nested list
arr2d = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(arr2d)
# [[1 2 3]
# [4 5 6]
# [7 8 9]]
# Array 3D
arr3d = np.array([[[1, 2], [3, 4]],
[[5, 6], [7, 8]]])
print(arr3d.shape) # (2, 2, 2)
# Menentukan tipe data secara eksplisit
arr_float = np.array([1, 2, 3], dtype=np.float64)
print(arr_float) # [1. 2. 3.]
print(arr_float.dtype) # float64
arr_int = np.array([1.5, 2.7, 3.9], dtype=np.int32)
print(arr_int) # [1 2 3] (dibulatkan ke bawah)
Array dengan Nilai Konstanta
import numpy as np # Array berisi nol zeros = np.zeros((3, 4)) print(zeros) # [[0. 0. 0. 0.] # [0. 0. 0. 0.] # [0. 0. 0. 0.]] # Array berisi satu ones = np.ones((2, 3)) print(ones) # [[1. 1. 1.] # [1. 1. 1.]] # Array berisi nilai tertentu full_arr = np.full((2, 3), 7) print(full_arr) # [[7 7 7] # [7 7 7]] # Matriks identitas eye = np.eye(4) print(eye) # [[1. 0. 0. 0.] # [0. 1. 0. 0.] # [0. 0. 1. 0.] # [0. 0. 0. 1.]] # Array kosong (nilai random di memori) empty = np.empty((2, 2)) print(empty) # Nilai tidak terdefinisi
Array dengan Deret Angka
import numpy as np # Arange — seperti range() tapi menghasilkan array arr_range = np.arange(0, 10, 2) print(arr_range) # [0 2 4 6 8] # Linspace — N titik yang terdistribusi merata arr_lin = np.linspace(0, 1, 5) print(arr_lin) # [0. 0.25 0.5 0.75 1. ] # Logspace — titik pada skala logaritmik arr_log = np.logspace(1, 3, 4) print(arr_log) # [ 10. 46.42 215.44 1000. ] # Membuat array dengan step tertentu arr_step = np.arange(0, 1, 0.1) print(arr_step) # [0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
4. Operasi Array
Keunggulan utama NumPy adalah operasi vektorisasi — operasi dilakukan pada seluruh elemen array sekaligus tanpa perlu loop. Ini jauh lebih cepat dari loop Python biasa.
Aritmatika Element-wise
import numpy as np a = np.array([10, 20, 30, 40]) b = np.array([1, 2, 3, 4]) # Operasi element-wise (per elemen) print(a + b) # [11 22 33 44] — penjumlahan print(a - b) # [ 9 18 27 36] — pengurangan print(a * b) # [ 10 40 90 160] — perkalian print(a / b) # [10. 10. 10. 10.] — pembagian print(a ** b) # [ 10 400 27000 2560000] — pangkat print(a % b) # [0 0 0 0] — modulus # Operasi dengan skalar (scalar) print(a + 5) # [15 25 35 45] print(a * 2) # [20 40 60 80] print(a / 10) # [1. 2. 3. 4.] # Operasi matematika universal (ufunc) print(np.sqrt(a)) # [3.16 4.47 5.48 6.32] — akar kuadrat print(np.exp(a)) # Eksponensial print(np.log(a)) # Logaritma natural print(np.sin(a)) # Sinus print(np.abs(-a)) # [10 20 30 40] — nilai absolut
Perbandingan dan Logika
import numpy as np a = np.array([1, 5, 10, 15, 20]) # Perbandingan — menghasilkan boolean array print(a > 10) # [False False False True True] print(a == 5) # [False True False False False] print(a != 1) # [False True True True True] # Boolean indexing — filter array mask = a > 10 print(a[mask]) # [15 20] # Kondisi logika print(np.logical_and(a > 5, a < 20)) # [False False True True False] print(np.logical_or(a < 3, a > 18)) # [ True False False False True] # np.where — seperti ternary untuk array hasil = np.where(a > 10, "besar", "kecil") print(hasil) # ['kecil' 'kecil' 'kecil' 'besar' 'besar']
5. Indexing dan Slicing
NumPy memperluas konsep indexing dan slicing Python ke dimensi yang lebih tinggi. Anda bisa mengakses, mengubah, dan memfilter elemen array dengan sangat fleksibel.
Indexing 1D
import numpy as np arr = np.array([10, 20, 30, 40, 50, 60, 70]) # Index positif (dari depan) print(arr[0]) # 10 print(arr[3]) # 40 # Index negatif (dari belakang) print(arr[-1]) # 70 print(arr[-3]) # 50 # Slicing [start:stop:step] print(arr[1:5]) # [20 30 40 50] print(arr[::2]) # [10 30 50 70] — setiap 2 elemen print(arr[::-1]) # [70 60 50 40 30 20 10] — balik urutan # Mengubah elemen dengan slicing arr[0:3] = 99 print(arr) # [99 99 99 40 50 60 70]
Indexing 2D (Matriks)
import numpy as np
matriks = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
# Akses elemen: [baris, kolom]
print(matriks[0, 0]) # 1 (baris 0, kolom 0)
print(matriks[1, 2]) # 7 (baris 1, kolom 2)
print(matriks[-1, -1]) # 12 (baris terakhir, kolom terakhir)
# Slicing baris dan kolom
print(matriks[0, :]) # [1 2 3 4] — seluruh baris 0
print(matriks[:, 1]) # [ 2 6 10] — seluruh kolom 1
print(matriks[0:2, 1:3]) # [[2 3] [6 7]] — sub-matriks
# Boolean indexing pada 2D
print(matriks[matriks > 6]) # [ 7 8 9 10 11 12]
# Fancy indexing — akses dengan list index
print(matriks[[0, 2], :]) # Baris 0 dan 2
# [[ 1 2 3 4]
# [ 9 10 11 12]]
Slicing di NumPy menghasilkan view (referensi), bukan copy. Mengubah slice akan mengubah array asli! Gunakan arr.copy() jika ingin membuat salinan independen.
6. Broadcasting
Broadcasting adalah mekanisme NumPy untuk melakukan operasi pada array dengan ukuran berbeda tanpa perlu menyalin data. NumPy akan secara otomatis "menyiarkan" array yang lebih kecil agar sesuai dengan array yang lebih besar.
Aturan Broadcasting
┌──────────────────────────────────────────────────────────┐ │ ATURAN BROADCASTING │ │ │ │ Rule 1: Jika array berbeda jumlah dimensi, │ │ tambah 1 di depan shape yang lebih kecil │ │ │ │ Rule 2: Ukuran 1 bisa "ditarik" agar cocok │ │ │ │ Rule 3: Jika ukuran tidak cocok dan bukan 1, error! │ │ │ │ Contoh: │ │ A (3, 4) + B (4,) → B jadi (1,4) lalu (3,4) │ │ A (3, 4) + C (3, 1) → C ditarik jadi (3, 4) │ │ A (3, 4) + D (3,) → ERROR! (tidak cocok) │ └──────────────────────────────────────────────────────────┘
Contoh Broadcasting
import numpy as np
# Broadcasting skalar ke array
arr = np.array([[1, 2, 3],
[4, 5, 6]])
print(arr + 10)
# [[11 12 13]
# [14 15 16]]
# Broadcasting vektor baris ke matriks
arr2d = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
row = np.array([10, 20, 30])
print(arr2d + row)
# [[11 22 33]
# [14 25 36]
# [17 28 39]]
# Broadcasting vektor kolom ke matriks
col = np.array([[100], [200], [300]])
print(arr2d + col)
# [[101 102 103]
# [204 205 206]
# [307 308 309]]
# Normalisasi data dengan broadcasting
data = np.array([[85, 90, 78],
[92, 88, 95],
[76, 82, 80]])
mean = data.mean(axis=0) # Rata-rata per kolom
std = data.std(axis=0) # Standar deviasi per kolom
normalized = (data - mean) / std
print(normalized)
# Data terstandarisasi (mean=0, std=1 per kolom)
7. Fungsi Statistik
NumPy menyediakan fungsi statistik lengkap yang bisa diterapkan pada seluruh array atau sepanjang axis tertentu.
import numpy as np
data = np.array([[85, 90, 78],
[92, 88, 95],
[76, 82, 80],
[90, 95, 88]])
# Statistik dasar
print(np.mean(data)) # 86.17 — rata-rata keseluruhan
print(np.median(data)) # 86.5 — median
print(np.std(data)) # 6.27 — standar deviasi
print(np.var(data)) # 39.31 — varians
print(np.min(data)) # 76 — nilai minimum
print(np.max(data)) # 95 — nilai maximum
print(np.sum(data)) # 1034 — total
# Statistik per axis
# axis=0 → operasi sepanjang baris (hasil per kolom)
# axis=1 → operasi sepanjang kolom (hasil per baris)
print(np.mean(data, axis=0)) # [85.75 88.75 85.25]
print(np.mean(data, axis=1)) # [84.33 91.67 79.33 91. ]
print(np.max(data, axis=1)) # [90 95 82 95]
# Kumulatif
print(np.cumsum([1, 2, 3, 4])) # [ 1 3 6 10] — jumlah kumulatif
print(np.cumprod([1, 2, 3, 4])) # [ 1 2 6 24] — perkalian kumulatif
# Persentil dan kuartil
print(np.percentile(data, 50)) # 86.5 (sama dengan median)
print(np.percentile(data, [25, 50, 75])) # [81. 86.5 91. ]
8. Reshaping dan Manipulasi
NumPy memungkinkan Anda mengubah bentuk (shape) array tanpa mengubah datanya. Ini sangat berguna saat mempersiapkan data untuk machine learning atau visualisasi.
import numpy as np # Reshape array arr = np.arange(12) print(arr) # [ 0 1 2 3 4 5 6 7 8 9 10 11] # Reshape ke 3x4 reshaped = arr.reshape(3, 4) print(reshaped) # [[ 0 1 2 3] # [ 4 5 6 7] # [ 8 9 10 11]] # Reshape ke 4x3 print(arr.reshape(4, 3)) # [[ 0 1 2] # [ 3 4 5] # [ 6 7 8] # [ 9 10 11]] # Gunakan -1 agar NumPy menghitung otomatis print(arr.reshape(2, -1)) # 2 baris, kolom dihitung → (2, 6) print(arr.reshape(-1, 6)) # baris dihitung, 6 kolom → (2, 6) # Flatten — ratakan ke 1D flat = reshaped.flatten() print(flat) # [ 0 1 2 3 4 5 6 7 8 9 10 11] # Transpose — tukar baris dan kolom print(reshaped.T) # [[ 0 4 8] # [ 1 5 9] # [ 2 6 10] # [ 3 7 11]] # Stack — gabungkan array a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) print(np.vstack([a, b])) # Vertical stack # [[1 2 3] # [4 5 6]] print(np.hstack([a, b])) # Horizontal stack # [1 2 3 4 5 6] # Split — pisahkan array arr = np.arange(9).reshape(3, 3) print(np.vsplit(arr, 3)) # Split jadi 3 bagian (baris) print(np.hsplit(arr, 3)) # Split jadi 3 bagian (kolom)
9. Linear Algebra
NumPy memiliki modul numpy.linalg yang menyediakan fungsi aljabar linear lengkap — perkalian matriks, determinan, invers, dekomposisi, dan lainnya.
import numpy as np
A = np.array([[1, 2],
[3, 4]])
B = np.array([[5, 6],
[7, 8]])
# Perkalian matriks (dot product)
print(np.dot(A, B))
# [[19 22]
# [43 50]]
# Atau gunakan @ operator (Python 3.5+)
print(A @ B)
# [[19 22]
# [43 50]]
# Perkalian element-wise (bukan dot product!)
print(A * B)
# [[ 5 12]
# [21 32]]
# Transpose
print(A.T)
# [[1 3]
# [2 4]]
# Determinan
det = np.linalg.det(A)
print(f"Determinan: {det:.2f}") # Determinan: -2.00
# Invers matriks
inv_A = np.linalg.inv(A)
print(inv_A)
# [[-2. 1. ]
# [ 1.5 -0.5]]
# Verifikasi: A * A_inv = Identity
print(np.round(A @ inv_A, 10))
# [[1. 0.]
# [0. 1.]]
# Eigenvalues dan eigenvectors
eigenvalues, eigenvectors = np.linalg.eig(A)
print(f"Eigenvalues: {eigenvalues}")
print(f"Eigenvectors:\n{eigenvectors}")
# Sistem persamaan linear: Ax = b
# 2x + 3y = 8
# 4x + 5y = 14
A_eq = np.array([[2, 3], [4, 5]])
b_eq = np.array([8, 14])
x = np.linalg.solve(A_eq, b_eq)
print(f"Solusi: x={x[0]}, y={x[1]}") # x=1.0, y=2.0
# Norm (panjang vektor)
v = np.array([3, 4])
print(np.linalg.norm(v)) # 5.0 (Euclidean norm)
print(np.linalg.norm(v, 1)) # 7.0 (L1 norm / Manhattan)
10. Random Number Generation
Modul numpy.random menyediakan generator angka acak yang cepat dan kaya fitur — sangat penting untuk simulasi, sampling, dan inisialisasi model machine learning.
import numpy as np
# Set seed untuk reproducibility
np.random.seed(42)
# Random float antara 0 dan 1
print(np.random.rand(3)) # 3 angka random
print(np.random.rand(2, 3)) # Matriks 2x3
# Random integer
print(np.random.randint(1, 100, size=5)) # 5 angka 1-99
print(np.random.randint(1, 10, size=(3, 3))) # Matriks 3x3
# Distribusi normal (Gaussian)
normal = np.random.randn(1000) # mean=0, std=1
print(f"Mean: {normal.mean():.2f}") # ≈ 0
print(f"Std: {normal.std():.2f}") # ≈ 1
# Distribusi normal dengan mean dan std tertentu
nilai_ujian = np.random.normal(loc=75, scale=10, size=1000)
print(f"Rata-rata: {nilai_ujian.mean():.2f}") # ≈ 75
print(f"Std: {nilai_ujian.std():.2f}") # ≈ 10
# Pilihan random dari array
buah = ["apel", "mangga", "jeruk", "pisang", "anggur"]
pilihan = np.random.choice(buah, size=10, replace=True)
print(pilihan) # 10 buah random (boleh duplikat)
# Shuffle array (in-place)
arr = np.arange(10)
np.random.shuffle(arr)
print(arr) # Acak!
# Permutasi (mengembalikan array baru)
arr2 = np.arange(10)
print(np.random.permutation(arr2)) # Array baru yang diacak
11. Tips dan Trik NumPy
Praktik Terbaik
import numpy as np
# 1. Hindari loop — gunakan vektorisasi
# ❌ Lambat
arr = np.arange(1000000)
hasil_slow = []
for x in arr:
hasil_slow.append(x ** 2)
# ✅ Cepat (100x lebih cepat)
hasil_fast = arr ** 2
# 2. Gunakan .shape dan .dtype untuk inspeksi
data = np.random.randn(100, 5)
print(f"Shape: {data.shape}") # (100, 5)
print(f"Dtype: {data.dtype}") # float64
print(f"Size: {data.size}") # 500
print(f"NDim: {data.ndim}") # 2
# 3. Gunakan dtype hemat memori
big_arr = np.arange(1000000, dtype=np.float32) # 4 byte/elem
small_arr = np.arange(1000000, dtype=np.float64) # 8 byte/elem
print(f"Float32: {big_arr.nbytes / 1e6:.1f} MB") # 4.0 MB
print(f"Float64: {small_arr.nbytes / 1e6:.1f} MB") # 8.0 MB
# 4. np.where untuk conditional replacement
arr = np.array([1, -2, 3, -4, 5])
cleaned = np.where(arr < 0, 0, arr)
print(cleaned) # [1 0 3 0 5]
# 5. np.unique — ambil nilai unik
data = np.array([1, 2, 2, 3, 3, 3, 4])
unik, counts = np.unique(data, return_counts=True)
print(f"Unik: {unik}") # [1 2 3 4]
print(f"Counts: {counts}") # [1 2 3 1]
Selalu gunakan vektorisasi NumPy alih-alih loop Python. Perbandingan kecepatan: untuk array 1 juta elemen, loop Python butuh ~500ms, sedangkan operasi NumPy hanya ~5ms — 100x lebih cepat!
12. Quiz: Uji Pemahamanmu!
Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang NumPy: