Indexing dan Slicing
Indexing memilih nilai pada posisi tertentu, sedangkan slicing memilih rentang pada satu atau beberapa axis. Slicing pada list Python membuat list baru. Basic slicing pada ndarray menghasilkan view yang berbagi data dengan array asal. Membaca elemen melalui advanced indexing dengan array integer atau Boolean menghasilkan copy.
View tidak menyalin data. Karena view dan array asal memakai data yang sama, perubahan melalui view juga mengubah elemen terkait pada array asal.
Operasi Array Satu Dimensi
Array satu dimensi memakai sintaks indeks Python. Basic slicing seperti a[1:4] menghasilkan view, sehingga perubahan melalui view juga mengubah elemen yang sama di a.
import numpy as np
# Membuat array 1D
a = np.linspace(0, 7, 8)
print("Array asal:", a) # Output: Array asal: [0. 1. 2. 3. 4. 5. 6. 7.]
# Indexing elemen tunggal
print("Elemen pada indeks 3:", a[3]) # Output: Elemen pada indeks 3: 3.0
print("Elemen terakhir:", a[-1]) # Output: Elemen terakhir: 7.0
# Slicing dasar
print("Slice [2:6]:", a[2:6]) # Output: Slice [2:6]: [2. 3. 4. 5.]
print("Slice [3:-2]:", a[3:-2]) # Output: Slice [3:-2]: [3. 4. 5.]
# Modifikasi melalui slicing (mengubah array asli)
a[:3] = 0
print("Setelah a[:3] = 0:", a) # Output: Setelah a[:3] = 0: [0. 0. 0. 3. 4. 5. 6. 7.]Contoh berikut mengubah view dan copy secara terpisah. View berbagi penyimpanan dengan array asli, sedangkan .copy() membuat data baru yang terpisah.
import numpy as np
# Array original
original = np.array([1, 2, 3, 4, 5])
print("Original:", original) # Output: Original: [1 2 3 4 5]
# Membuat view melalui slicing
view = original[1:4]
print("View:", view) # Output: View: [2 3 4]
# Mengubah view (memengaruhi array original)
view[0] = 999
print("Setelah mengubah view:")
print("Original:", original) # Output: Original: [ 1 999 3 4 5]
print("View:", view) # Output: View: [999 3 4]
# Membuat copy eksplisit
copy_array = original[1:4].copy()
copy_array[0] = 777
print("Setelah mengubah copy:")
print("Original:", original) # Output: Original: [ 1 999 3 4 5]
print("Salinan:", copy_array) # Output: Salinan: [777 3 4]Operasi Array Multidimensi
Pada seleksi multidimensi, setiap entri yang dipisahkan koma menangani satu dimensi array, dimulai dari dimensi pertama. Indeks berupa bilangan bulat menghapus dimensi itu dari array hasil, sedangkan potongan seperti : mempertahankan dimensi tersebut. Contohnya, pada array dua dimensi a, a[1, :] menghasilkan array satu dimensi dari baris kedua, sedangkan a[1:2, :] tetap menghasilkan array dua dimensi berisi satu baris.
import numpy as np
# Membuat array 2D
a = np.array([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.],
[10., 11., 12.]])
print("Array 2D:")
print(a)
# Output:
# [[ 1. 2. 3.]
# [ 4. 5. 6.]
# [ 7. 8. 9.]
# [10. 11. 12.]]
# Indexing elemen spesifik
print("a[2,1]:", a[2,1]) # Output: a[2,1]: 8.0
# Slicing baris
print("a[1,:]:", a[1,:]) # Output: a[1,:]: [4. 5. 6.]
# Slicing kolom
print("a[:,2]:", a[:,2]) # Output: a[:,2]: [ 3. 6. 9. 12.]Kombinasi slice pada beberapa axis memilih subarray berbentuk persegi panjang atau berselang tanpa menulis loop:
import numpy as np
# Array 2D untuk demonstrasi
a = np.array([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.],
[10., 11., 12.]])
# Slicing subarray
print("a[1:3, 0:2]:")
print(a[1:3, 0:2])
# Output:
# [[4. 5.]
# [7. 8.]]
# Slicing dengan step
print("a[::2, :]:")
print(a[::2, :])
# Output:
# [[1. 2. 3.]
# [7. 8. 9.]]
# Slicing kolom dengan step
print("a[:, ::2]:")
print(a[:, ::2])
# Output:
# [[ 1. 3.]
# [ 4. 6.]
# [ 7. 9.]
# [10. 12.]]Ringkasan Operasi Dua Dimensi
Tabel berikut mengumpulkan bentuk indeks dan slice untuk array dua dimensi di satu tempat, lengkap dengan bentuk hasil masing-masing.
| Operasi | Deskripsi | Contoh Hasil |
|---|---|---|
a[2,1] | Elemen baris , kolom | Satu nilai: 8.0 |
a[1,:] | Seluruh baris | Array satu dimensi: [4. 5. 6.] |
a[:,2] | Seluruh kolom | Array satu dimensi: [3. 6. 9. 12.] |
a[1:3, 0:2] | Subarray baris , kolom | Array dua dimensi: [[4. 5.], [7. 8.]] |
a[::2, :] | Setiap baris kedua | Array dua dimensi dengan baris |
a[:, ::2] | Setiap kolom kedua | Array dua dimensi dengan kolom |
Advanced Indexing
Advanced indexing memakai array integer atau Boolean untuk memilih elemen secara bebas dan selalu menghasilkan copy. Pada sumber satu dimensi, bentuk array indeks menentukan bentuk hasil. Pada sumber multidimensi, NumPy menerapkan broadcasting pada array indeks, lalu menggabungkan bentuk array indeks dengan dimensi yang tersisa dari basic slicing.
import numpy as np
# Array untuk demonstrasi
a = np.array([0, 1, 2, 3, 4])
print("Array asal:", a) # Output: Array asal: [0 1 2 3 4]
# Indexing dengan list indeks
i = [1, 3, 2, 1, 4]
print("Array index:", i) # Output: Array index: [1, 3, 2, 1, 4]
print("a[i]:", a[i]) # Output: a[i]: [1 3 2 1 4]
# Indexing dan reshaping dengan array 2D indeks
i = np.array([[1, 2], [3, 4]])
print("Index 2D array:")
print(i)
# Output:
# [[1 2]
# [3 4]]
print("a[i]:")
print(a[i])
# Output:
# [[1 2]
# [3 4]]Boolean mask memilih posisi yang bernilai True. Jika bentuk mask sama dengan bentuk sumber, nilai yang terpilih dikembalikan sebagai copy satu dimensi.
import numpy as np
# Array untuk demonstrasi
a = np.linspace(0, 5, 6)
print("Array:", a) # Output: Array: [0. 1. 2. 3. 4. 5.]
# Membuat boolean mask
mask = np.array([True, False, True, False, True, False])
print("Mask boolean:", mask) # Output: Mask boolean: [ True False True False True False]
print("a[mask]:", a[mask]) # Output: a[mask]: [0. 2. 4.]
# Boolean mask dari kondisi
condition_mask = a % 2 == 0
print("Mask kondisi (a % 2 == 0):", condition_mask) # Output: Mask kondisi (a % 2 == 0): [ True False True False True False]
print("a[condition_mask]:", a[condition_mask]) # Output: a[condition_mask]: [0. 2. 4.]
# Boolean mask dengan kondisi kompleks
complex_mask = (a > 1) & (a < 4)
print("Mask gabungan (a > 1) & (a < 4):", complex_mask) # Output: Mask gabungan (a > 1) & (a < 4): [False False True True False False]
print("a[complex_mask]:", a[complex_mask]) # Output: a[complex_mask]: [2. 3.]Advanced indexing dan basic slicing dapat dipakai dalam seleksi yang sama. Jika sebuah seleksi memuat advanced indexing, seleksi tersebut tetap menghasilkan copy:
import numpy as np
# Array 2D untuk demonstrasi
a = np.arange(24).reshape(4, 6)
print("Array 2D:")
print(a)
# Output:
# [[ 0 1 2 3 4 5]
# [ 6 7 8 9 10 11]
# [12 13 14 15 16 17]
# [18 19 20 21 22 23]]
# Kombinasi slicing dan indexing
print("a[1:3, [0, 2, 5]]:")
print(a[1:3, [0, 2, 5]])
# Output:
# [[ 6 8 11]
# [12 14 17]]
# Boolean indexing pada baris, slicing pada kolom
row_mask = np.array([True, False, True, False])
print("a[row_mask, 2:5]:")
print(a[row_mask, 2:5])
# Output:
# [[ 2 3 4]
# [14 15 16]]Teknik Lanjutan
Bagian ketiga pada slice adalah step. Nilai ini memilih interval teratur, menerima nilai negatif untuk menelusuri urutan terbalik, dan dapat dipakai secara terpisah pada setiap axis.
import numpy as np
# Array untuk demonstrasi
a = np.arange(20)
print("Array:", a) # Output: Array: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
# Slicing dengan step
print("a[::2] (setiap elemen kedua):", a[::2]) # Output: a[::2] (setiap elemen kedua): [ 0 2 4 6 8 10 12 14 16 18]
print("a[1::3] (mulai indeks 1, setiap ketiga):", a[1::3]) # Output: a[1::3] (mulai indeks 1, setiap ketiga): [ 1 4 7 10 13 16 19]
print("a[::-1] (membalik array):", a[::-1]) # Output: a[::-1] (membalik array): [19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0]
# Step pada array 2D
b = np.arange(12).reshape(3, 4)
print("Array 2D:")
print(b)
# Output:
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print("b[::2, ::2] (setiap baris dan kolom kedua):")
print(b[::2, ::2])
# Output:
# [[ 0 2]
# [ 8 10]]Elipsis (...) mewakili full slice pada semua dimensi yang tidak disebutkan. Notasi ini mempersingkat seleksi pada array berdimensi tinggi.
import numpy as np
# Array 3D untuk demonstrasi
a = np.arange(24).reshape(2, 3, 4)
print("Array 3D shape:", a.shape) # Output: Array 3D shape: (2, 3, 4)
# Menggunakan ellipsis
print("a[0, ...] (sama dengan a[0, :, :]):")
print(a[0, ...])
# Output:
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print("a[..., 2] (sama dengan a[:, :, 2]):")
print(a[..., 2])
# Output:
# [[ 2 6 10]
# [14 18 22]]
print("a[1, ..., ::2] (sama dengan a[1, :, ::2]):")
print(a[1, ..., ::2])
# Output:
# [[12 14]
# [16 18]
# [20 22]]Indexing dengan Boolean Mask
Boolean indexing memeriksa mask pada setiap posisi. Nilai True memilih elemen, sedangkan False melewatinya.
import numpy as np
# Array untuk demonstrasi
a = np.linspace(0, 5, 6)
print("Array:", a) # Output: Array: [0. 1. 2. 3. 4. 5.]
# Boolean mask manual
mask = np.array([True, False, True, False, True, False], dtype=bool)
print("Mask manual:", mask) # Output: Mask manual: [ True False True False True False]
print("a[mask]:", a[mask]) # Output: a[mask]: [0. 2. 4.]
# Boolean mask dari perbandingan
greater_than_2 = a > 2
print("a > 2:", greater_than_2) # Output: a > 2: [False False False True True True]
print("a[a > 2]:", a[a > 2]) # Output: a[a > 2]: [3. 4. 5.]
# Boolean mask dengan kondisi ganda
even_and_greater_than_1 = (a % 2 == 0) & (a > 1)
print("(a % 2 == 0) & (a > 1):", even_and_greater_than_1) # Output: (a % 2 == 0) & (a > 1): [False False True False True False]
print("a[even_and_greater_than_1]:", a[even_and_greater_than_1]) # Output: a[even_and_greater_than_1]: [2. 4.]Boolean mask dengan shape yang sama memilih elemen yang cocok dari array dua dimensi lalu mengembalikannya sebagai hasil satu dimensi:
import numpy as np
# Array 2D untuk demonstrasi
a = np.arange(12).reshape(3, 4)
print("Array 2D:")
print(a)
# Output:
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# Boolean mask untuk elemen tertentu
mask = a > 5
print("Mask untuk a > 5:")
print(mask)
# Output:
# [[False False False False]
# [False False True True]
# [ True True True True]]
print("a[mask]:", a[mask]) # Output: a[mask]: [ 6 7 8 9 10 11]
# Boolean indexing dengan assignment
a[a < 5] = 0
print("Setelah a[a < 5] = 0:")
print(a)
# Output:
# [[ 0 0 0 0]
# [ 0 5 6 7]
# [ 8 9 10 11]]Bedakan membaca hasil seleksi dan memberi nilai. selected = a[mask] membuat copy, tetapi a[a < 5] = 0 menulis langsung ke posisi terpilih pada a. Nilai 5 tetap ada karena kondisi memakai < 5, bukan <= 5.
Indexing dengan Array Indeks
Istilah fancy indexing biasanya merujuk pada advanced indexing dengan array integer. Cara ini dapat mengurutkan ulang posisi, memilih posisi yang sama beberapa kali, atau menyusun hasil mengikuti bentuk array indeks.
import numpy as np
# Array untuk demonstrasi
a = np.array([10, 20, 30, 40, 50, 60])
print("Array:", a) # Output: Array: [10 20 30 40 50 60]
# Fancy indexing dengan list indeks
indices = [0, 2, 4, 1]
print("Index:", indices) # Output: Index: [0, 2, 4, 1]
print("a[indices]:", a[indices]) # Output: a[indices]: [10 30 50 20]
# Fancy indexing dengan array NumPy
np_indices = np.array([5, 1, 3, 1, 0])
print("Index NumPy:", np_indices) # Output: Index NumPy: [5 1 3 1 0]
print("a[np_indices]:", a[np_indices]) # Output: a[np_indices]: [60 20 40 20 10]
# Fancy indexing dengan array 2D indeks
indices_2d = np.array([[0, 1], [2, 3]])
print("Index 2D:")
print(indices_2d)
# Output:
# [[0 1]
# [2 3]]
print("a[indices_2d]:")
print(a[indices_2d])
# Output:
# [[10 20]
# [30 40]]Pada array dua dimensi, index integer dapat memilih seluruh baris atau memasangkan koordinat baris dan kolom elemen demi elemen:
import numpy as np
# Array 2D untuk demonstrasi
a = np.arange(24).reshape(4, 6)
print("Array 2D:")
print(a)
# Output:
# [[ 0 1 2 3 4 5]
# [ 6 7 8 9 10 11]
# [12 13 14 15 16 17]
# [18 19 20 21 22 23]]
# Fancy indexing untuk baris tertentu
row_indices = [0, 2, 3]
print("a[row_indices, :]:")
print(a[row_indices, :])
# Output:
# [[ 0 1 2 3 4 5]
# [12 13 14 15 16 17]
# [18 19 20 21 22 23]]
# Fancy indexing untuk elemen spesifik
row_idx = [0, 1, 2, 3]
col_idx = [1, 2, 3, 4]
print("a[row_idx, col_idx]:", a[row_idx, col_idx]) # Output: a[row_idx, col_idx]: [ 1 8 15 22]
# Kombinasi fancy indexing dengan slicing
print("a[[0, 2], 1:4]:")
print(a[[0, 2], 1:4])
# Output:
# [[ 1 2 3]
# [13 14 15]]Memilih dan Menyusun Ulang Data dalam Array
Aturan seleksi yang sama dapat dipakai untuk menyaring baris, mengambil sampel, dan menyusun ulang data tanpa menulis loop.
Contoh ini memperlihatkan mask dan pemberian nilai. Dalam analisis sebenarnya, konteks pengukuran harus menentukan ambang suhu dan aturan penggantian:
import numpy as np
# Simulasi data sensor suhu
temperatures = np.array([22.5, 25.1, 19.8, 30.2, 18.5, 27.3, 31.1, 24.8])
print("Data suhu:", temperatures) # Output: Data suhu: [22.5 25.1 19.8 30.2 18.5 27.3 31.1 24.8]
# Filter suhu normal (20-28 derajat)
normal_temp_mask = (temperatures >= 20) & (temperatures <= 28)
normal_temps = temperatures[normal_temp_mask]
print("Suhu normal:", normal_temps) # Output: Suhu normal: [22.5 25.1 27.3 24.8]
# Filter suhu ekstrem
extreme_temp_mask = (temperatures < 20) | (temperatures > 30)
extreme_temps = temperatures[extreme_temp_mask]
print("Suhu ekstrem:", extreme_temps) # Output: Suhu ekstrem: [19.8 30.2 18.5 31.1]
# Mengganti nilai ekstrem dengan nilai rata-rata
mean_temp = temperatures[normal_temp_mask].mean()
temperatures_cleaned = temperatures.copy()
temperatures_cleaned[extreme_temp_mask] = mean_temp
print("Data setelah cleaning:", temperatures_cleaned) # Output: Data setelah cleaning: [22.5 25.1 24.925 24.925 24.925 27.3 24.925 24.8 ]Untuk mengulang sampel dengan generator dan versi NumPy yang sama, gunakan seed yang tetap pada generator lokal:
import numpy as np
# Dataset simulasi
data = np.arange(100).reshape(10, 10)
print("Shape dataset:", data.shape) # Output: Shape dataset: (10, 10)
# Sampling baris acak dengan generator lokal
rng = np.random.default_rng(42)
sample_indices = rng.choice(10, size=5, replace=False)
sample_indices.sort()
print("Index sampel:", sample_indices) # Output: Index sampel: [0 3 4 5 7]
sampled_data = data[sample_indices, :]
print("Shape data sampel:", sampled_data.shape) # Output: Shape data sampel: (5, 10)
print("Tiga kolom pertama data sampel:")
print(sampled_data[:, :3])
# Output:
# [[ 0 1 2]
# [30 31 32]
# [40 41 42]
# [50 51 52]
# [70 71 72]]
# Reorganisasi kolom
column_order = [9, 0, 5, 2, 7, 1, 8, 3, 6, 4]
reorganized_data = data[:, column_order]
print("Baris pertama setelah ditata ulang:", reorganized_data[0, :]) # Output: Baris pertama setelah ditata ulang: [9 0 5 2 7 1 8 3 6 4]