Konsep Dasar Indexing dan Slicing
Indexing dan slicing adalah alat untuk mengekstrak data spesifik dari array NumPy. Bayangkan indexing sebagai penunjuk ke lokasi tepat, sedangkan slicing mengambil seluruh bagian sekaligus. Berbeda dengan list Python yang membuat copy, slicing NumPy membuat view yang berbagi memori dengan array asli.
Perilaku berbagi memori ini membuat NumPy sangat efisien tetapi memerlukan perhatian khusus untuk menghindari modifikasi yang tidak diinginkan. Dokumentasi indexing NumPy menyediakan contoh ekstensif pola indexing lanjutan ketika kamu butuh seleksi data yang lebih canggih.
Operasi Array 1D
Array satu dimensi menggunakan sintaks yang sama dengan list Python. Slicing mengembalikan view dari data, bukan copy, sehingga perubahan pada view akan mempengaruhi array asli.
import numpy as np# Membuat array 1Da = np.linspace(0, 7, 8)print("Array original:", a) # Output: Array original: [0. 1. 2. 3. 4. 5. 6. 7.]# Indexing elemen tunggalprint("Elemen ke-3:", a[3]) # Output: Elemen ke-3: 3.0print("Elemen terakhir:", a[-1]) # Output: Elemen terakhir: 7.0# Slicing dasarprint("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] = 0print("Setelah a[:3] = 0:", a) # Output: Setelah a[:3] = 0: [0. 0. 0. 3. 4. 5. 6. 7.]
Konsep penting dalam slicing NumPy adalah perbedaan antara view dan copy. View berbagi memori dengan array asli, sedangkan copy adalah duplikat independen.
import numpy as np# Array originaloriginal = np.array([1, 2, 3, 4, 5])print("Original:", original) # Output: Original: [1 2 3 4 5]# Membuat view melalui slicingview = original[1:4]print("View:", view) # Output: View: [2 3 4]# Mengubah view (mempengaruhi original)view[0] = 999print("Setelah mengubah view:")print("Original:", original) # Output: Original: [ 1 999 3 4 5]print("View:", view) # Output: View: [999 3 4]# Membuat copy eksplisitcopy_array = original[1:4].copy()copy_array[0] = 777print("Setelah mengubah copy:")print("Original:", original) # Output: Original: [ 1 999 3 4 5]print("Copy:", copy_array) # Output: Copy: [777 3 4]
Operasi Array Multidimensi
Array multidimensi menggunakan tuple integer untuk indexing. Setiap dimensi dipisahkan dengan koma dalam tanda kurung siku. Assignment dan slicing dapat dikombinasikan untuk operasi yang kompleks.
import numpy as np# Membuat array 2Da = 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 spesifikprint("a[2,1]:", a[2,1]) # Output: a[2,1]: 8.0# Slicing barisprint("a[1,:]:", a[1,:]) # Output: a[1,:]: [4. 5. 6.]# Slicing kolomprint("a[:,2]:", a[:,2]) # Output: a[:,2]: [ 3. 6. 9. 12.]
Slicing lanjutan memungkinkan pengambilan subarray dengan pola yang kompleks:
import numpy as np# Array 2D untuk demonstrasia = np.array([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.], [10., 11., 12.]])# Slicing subarrayprint("a[1:3, 0:2]:")print(a[1:3, 0:2])# Output:# [[4. 5.]# [7. 8.]]# Slicing dengan stepprint("a[::2, :]:")print(a[::2, :])# Output:# [[ 1. 2. 3.]# [ 7. 8. 9.]]# Slicing kolom dengan stepprint("a[:, ::2]:")print(a[:, ::2])# Output:# [[ 1. 3.]# [ 4. 6.]# [ 7. 9.]# [10. 12.]]
Ringkasan Operasi 2D
Operasi | Deskripsi | Contoh Hasil |
---|---|---|
a[2,1] | Elemen baris 2, kolom 1 | Satu nilai: 8.0 |
a[1,:] | Seluruh baris 1 | Array 1D: [4. 5. 6.] |
a[:,2] | Seluruh kolom 2 | Array 1D: [3. 6. 9. 12.] |
a[1:3, 0:2] | Subarray baris 1-2, kolom 0-1 | Array 2D: [[4. 5.], [7. 8.]] |
a[::2, :] | Setiap baris kedua | Array 2D dengan baris 0, 2 |
a[:, ::2] | Setiap kolom kedua | Array 2D dengan kolom 0, 2 |
Advanced Indexing
Advanced indexing memungkinkan penggunaan array integer atau boolean untuk mengakses elemen dengan pola yang kompleks. Indexing dengan array integer membuat copy baru daripada view. Copy memiliki shape yang sama dengan index array.
import numpy as np# Array untuk demonstrasia = np.array([0, 1, 2, 3, 4])print("Array original:", a) # Output: Array original: [0 1 2 3 4]# Indexing dengan list indeksi = [1, 3, 2, 1, 4]print("Index array:", i) # Output: Index array: [1, 3, 2, 1, 4]print("a[i]:", a[i]) # Output: a[i]: [1 3 2 1 4]# Indexing dan reshaping dengan array 2D indeksi = 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 adalah teknik powerful untuk filtering data berdasarkan kondisi tertentu. Indexing dengan array boolean mengambil elemen di mana nilai True ditemukan.
import numpy as np# Array untuk demonstrasia = np.linspace(0, 5, 6)print("Array:", a) # Output: Array: [0. 1. 2. 3. 4. 5.]# Membuat boolean maskmask = np.array([True, False, True, False, True, False])print("Boolean mask:", mask) # Output: Boolean mask: [ True False True False True False]print("a[mask]:", a[mask]) # Output: a[mask]: [0. 2. 4.]# Boolean mask dari kondisicondition_mask = a % 2 == 0print("Condition mask (a % 2 == 0):", condition_mask) # Output: Condition mask (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 komplekscomplex_mask = (a > 1) & (a < 4)print("Complex mask (a > 1) & (a < 4):", complex_mask) # Output: Complex mask (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 dapat dikombinasikan dengan slicing regular untuk operasi yang sangat fleksibel:
import numpy as np# Array 2D untuk demonstrasia = 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 indexingprint("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 kolomrow_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
NumPy menyediakan berbagai teknik slicing yang memungkinkan manipulasi data yang efisien dan fleksibel. Step parameter memungkinkan kamu mengambil elemen dengan interval tertentu, seperti mengambil setiap elemen kedua atau ketiga.
import numpy as np# Array untuk demonstrasia = 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 stepprint("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 2Db = 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]]
Ellipsis (...
) adalah shorthand untuk slice penuh pada dimensi yang tidak disebutkan. Sangat berguna untuk array dengan dimensi tinggi.
import numpy as np# Array 3D untuk demonstrasia = np.arange(24).reshape(2, 3, 4)print("Array 3D shape:", a.shape) # Output: Array 3D shape: (2, 3, 4)# Menggunakan ellipsisprint("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]]
Boolean Indexing
Boolean indexing menggunakan array boolean untuk memfilter elemen berdasarkan kondisi tertentu. True indexes mengambil elemen di target array, sedangkan False mengabaikannya.
import numpy as np# Array untuk demonstrasia = np.linspace(0, 5, 6)print("Array:", a) # Output: Array: [0. 1. 2. 3. 4. 5.]# Boolean mask manualmask = np.array([True, False, True, False, True, False], dtype=bool)print("Manual mask:", mask) # Output: Manual mask: [ True False True False True False]print("a[mask]:", a[mask]) # Output: a[mask]: [0. 2. 4.]# Boolean mask dari perbandingangreater_than_2 = a > 2print("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 gandaeven_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 indexing pada array 2D dapat diterapkan untuk filtering elemen berdasarkan kondisi:
import numpy as np# Array 2D untuk demonstrasia = 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 tertentumask = a > 5print("Mask 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 assignmenta[a < 5] = 0print("Setelah a[a < 5] = 0:")print(a)# Output:# [[ 0 0 0 0]# [ 0 0 6 7]# [ 8 9 10 11]]
Fancy Indexing
Fancy indexing menggunakan array integer untuk mengakses elemen dengan urutan atau pola tertentu. Teknik ini sangat berguna untuk data sampling dan reorganisasi.
import numpy as np# Array untuk demonstrasia = np.array([10, 20, 30, 40, 50, 60])print("Array:", a) # Output: Array: [10 20 30 40 50 60]# Fancy indexing dengan list indeksindices = [0, 2, 4, 1]print("Indices:", indices) # Output: Indices: [0, 2, 4, 1]print("a[indices]:", a[indices]) # Output: a[indices]: [10 30 50 20]# Fancy indexing dengan array NumPynp_indices = np.array([5, 1, 3, 1, 0])print("NumPy indices:", np_indices) # Output: NumPy indices: [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 indeksindices_2d = np.array([[0, 1], [2, 3]])print("Indices 2D:")print(indices_2d)# Output:# [[0 1]# [2 3]]print("a[indices_2d]:")print(a[indices_2d])# Output:# [[10 20]# [30 40]]
Fancy indexing pada array 2D memungkinkan seleksi baris dan kolom dengan pola yang kompleks:
import numpy as np# Array 2D untuk demonstrasia = 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 tertenturow_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 spesifikrow_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 slicingprint("a[[0, 2], 1:4]:")print(a[[0, 2], 1:4])# Output:# [[ 1 2 3]# [13 14 15]]
Aplikasi Praktis
Indexing dan slicing memiliki banyak aplikasi praktis dalam analisis data dan machine learning.
Teknik filtering sangat berguna untuk preprocessing data dalam machine learning dan analisis statistik:
import numpy as np# Simulasi data sensor suhutemperatures = 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 ekstremextreme_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-ratamean_temp = temperatures[normal_temp_mask].mean()temperatures_cleaned = temperatures.copy()temperatures_cleaned[extreme_temp_mask] = mean_tempprint("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 ]
Sampling dan reorganisasi data adalah teknik penting untuk machine learning dan analisis dataset besar:
import numpy as np# Dataset simulasidata = np.arange(100).reshape(10, 10)print("Dataset shape:", data.shape) # Output: Dataset shape: (10, 10)# Random sampling barisnp.random.seed(42)sample_indices = np.random.choice(10, size=5, replace=False)sample_indices.sort()print("Sample indices:", sample_indices) # Output: Sample indices: [0 1 5 7 8]sampled_data = data[sample_indices, :]print("Sampled data shape:", sampled_data.shape) # Output: Sampled data shape: (5, 10)print("First 3 columns of sampled data:")print(sampled_data[:, :3])# Output:# [[ 0 1 2]# [10 11 12]# [50 51 52]# [70 71 72]# [80 81 82]]# Reorganisasi kolomcolumn_order = [9, 0, 5, 2, 7, 1, 8, 3, 6, 4]reorganized_data = data[:, column_order]print("Reorganized first row:", reorganized_data[0, :]) # Output: Reorganized first row: [9 0 5 2 7 1 8 3 6 4]