☀️Siang
AI & Data Science

Pandas & NumPy: Manipulasi Data Python

TOKEN

Panduan lengkap manipulasi data menggunakan NumPy dan Pandas — array operations, broadcasting, DataFrame, indexing, filtering, groupby, merge, dan export data ke berbagai format

Artikel: Pandas Numpy Artikel: Pandas Numpy


1. Pengenalan NumPy & Pandas

NumPy (Numerical Python) dan Pandas adalah dua library paling fundamental dalam ekosistem data science Python. NumPy menyediakan struktur data array multidimensi yang efisien, sementara Pandas menyediakan struktur data tabular (seperti spreadsheet) yang powerful untuk manipulasi dan analisis data.

Hubungan NumPy & Pandas

Aspek NumPy Pandas
Data Structurendarray (array N-dimensi)Series (1D) dan DataFrame (2D)
Tipe DataHomogen (satu tipe)Heterogen (campur tipe)
KekuatanKomputasi numerik cepatData manipulation & analysis
IndexInteger-basedLabel-based (bisa custom)
Missing DataTidak nativeNative (NaN handling)
Cocok untukMatrix, operasi matematika, MLCSV/Excel, data cleaning, EDA
Kecepatan🟢 Sangat cepat (C-optimized)🟡 Cepat (dibangun di atas NumPy)
Diagram: Ekosistem Data Science Python
Ekosistem Data Science Python

NumPy (Array dan Komputasi) Pandas Visualizatio...

Scikit-learn (Machine Learning)

SciPy (Scientific Computing) TensorFlow / PyTor...

Instalasi

Diagram: Cara Kerja Broadcasting
Cara Kerja Broadcasting

Aturan Broadcasting NumPy:

1. Jika dimensi berbeda, array yang lebih kecil...
2. Array dengan shape (1,) bisa di-broadcast ke...
3. Dimensi dengan ukuran 1 di-stretch agar match

Contoh:

arr (3x3) + scalar (1x1)

result (3x3)

("(1,2,3"), 10 ("(11,12,13"),

(4,5,6), (14,15,16),

(7,8,9)) (17,18,19))

arr (3x3) + vector (1x3)

result (3x3)

("(1,2,3"), (10,20,30) ("(11,22,33"),

(4,5,6), (14,25,36),

(7,8,9)) (17,28,39))

arr (3x3) + vector (3x1)

result (3x3)

("(1,2,3"), ("(10"), ("(11,12,13"),

(4,5,6), (20), (24,25,26),

(7,8,9)) (30)) (37,38,39))

Python — Broadcasting
import numpy as np

# Contoh Broadcasting
matriks = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])

# Scalar broadcasting
print(matriks * 10)
# [[10 20 30]
#  [40 50 60]
#  [70 80 90]]

# Vector broadcasting (baris)
kolom = np.array([[10], [20], [30]])  # shape (3,1)
print(matriks + kolom)
# [[11 12 13]
#  [24 25 26]
#  [37 38 39]]

# Normalisasi data (praktik umum)
data = np.array([
    [170, 65, 25],  # [tinggi_cm, berat_kg, umur]
    [180, 80, 30],
    [165, 55, 22],
    [175, 70, 28],
])

# Z-score normalisasi dengan broadcasting
mean = data.mean(axis=0)   # Mean per kolom
std = data.std(axis=0)     # Std per kolom
normalized = (data - mean) / std

print(f"Mean per kolom: {mean}")
print(f"Std per kolom:  {std}")
print(f"Normalized:\n{normalized}")

Lanjutan: Operasi Array yang Sering Digunakan

Python — Advanced NumPy
import numpy as np

# Reshape
arr = np.arange(12)
print(arr.reshape(3, 4))
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

# Stacking arrays
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])

print(np.vstack((a, b)))  # Vertical stack
# [[1 2] [3 4] [5 6] [7 8]]

print(np.hstack((a, b)))  # Horizontal stack
# [[1 2 5 6] [3 4 7 8]]

# Dot product (perkalian matriks)
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(np.dot(A, B))
# [[19 22]
#  [43 50]]

# Atau dengan operator @
print(A @ B)  # Sama dengan np.dot

# Linear algebra
m = np.array([[2, 1], [5, 3]])
print(f"Determinan: {np.linalg.det(m):.0f}")      # 1.0
print(f"Inverse:\n{np.linalg.inv(m)}")
print(f"Eigenvalues: {np.linalg.eig(m)[0]}")

# Simpan dan load array
np.save('data_array.npy', data)
loaded = np.save('data_array.npy')
np.savetxt('data_array.csv', data, delimiter=',')
loaded_csv = np.loadtxt('data_array.csv', delimiter=',')


4. Pandas: Series

Pandas Series adalah struktur data satu dimensi yang mirip dengan kolom di spreadsheet atau array dengan label (index). Series adalah blok bangunan dasar dari DataFrame.

Membuat Series

Python — Pandas Series
import pandas as pd

# Series dari list
s = pd.Series([10, 20, 30, 40, 50])
print(s)
# 0    10
# 1    20
# 2    30
# 3    40
# 4    50
# dtype: int64

# Series dengan custom index
suhu = pd.Series(
    [28.5, 30.2, 27.8, 31.5, 29.0],
    index=['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat'],
    name='Suhu Harian'
)
print(suhu)
# Senin     28.5
# Selasa    30.2
# Rabu      27.8
# Kamis     31.5
# Jumat     29.0
# Name: Suhu Harian, dtype: float64

# Series dari dictionary
penduduk = pd.Series({
    'Jakarta': 10560000,
    'Surabaya': 2870000,
    'Bandung': 2500000,
    'Medan': 2430000,
    'Semarang': 1750000
})
print(penduduk)

# Akses elemen
print(suhu['Rabu'])        # 27.8 (label-based)
print(suhu.iloc[2])        # 27.8 (position-based)
print(suhu['Senin':'Rabu'])  # Slicing (inklusif di Pandas!)

Operasi Series

Python — Series Operations
import pandas as pd

nilai = pd.Series({
    'Matematika': 85,
    'Fisika': 78,
    'Kimia': 92,
    'Biologi': 88,
    'Bahasa': 75
})

# Statistik
print(f"Rata-rata: {nilai.mean():.1f}")      # 83.6
print(f"Tertinggi: {nilai.idxmax()}")          # Kimia
print(f"Terendah:  {nilai.idxmin()}")          # Bahasa

# Filtering
print(nilai[nilai >= 85])  # Nilai >= 85

# Sorting
print(nilai.sort_values(ascending=False))  # Sort descending

# Apply function
def grade(score):
    if score >= 90: return 'A'
    elif score >= 80: return 'B'
    elif score >= 70: return 'C'
    else: return 'D'

grades = nilai.apply(grade)
print(grades)

# Value counts
print(grades.value_counts())


5. Pandas: DataFrame

DataFrame adalah struktur data utama Pandas — sebuah tabel 2D dengan baris dan kolom yang berlabel. DataFrame adalah ekensi dari Series dan menyimpan data heterogen (bisa campur tipe data dalam satu tabel).

Membuat DataFrame

Python — DataFrame Creation
import pandas as pd

# DataFrame dari dictionary
karyawan = pd.DataFrame({
    'Nama': ['Andi', 'Budi', 'Citra', 'Dewi', 'Eka'],
    'Departemen': ['IT', 'Finance', 'IT', 'HR', 'Finance'],
    'Usia': [28, 35, 24, 31, 29],
    'Gaji': [8500000, 12000000, 7000000, 9500000, 11000000],
    'Rating': [4.5, 3.8, 4.2, 4.0, 4.7]
})

print(karyawan)
#     Nama Departemen  Usia      Gaji  Rating
# 0   Andi         IT    28   8500000     4.5
# 1   Budi    Finance    35  12000000     3.8
# 2  Citra         IT    24   7000000     4.2
# 3   Dewi         HR    31   9500000     4.0
# 4    Eka    Finance    29  11000000     4.7

# Informasi DataFrame
print(f"Shape: {karyawan.shape}")         # (5, 5)
print(f"Kolom: {list(karyawan.columns)}")
print(f"Tipe data:\n{karyawan.dtypes}")
print(f"Info statistik:\n{karyawan.describe()}")

DataFrame Operations

Python — DataFrame Operations
import pandas as pd

karyawan = pd.DataFrame({
    'Nama': ['Andi', 'Budi', 'Citra', 'Dewi', 'Eka'],
    'Departemen': ['IT', 'Finance', 'IT', 'HR', 'Finance'],
    'Usia': [28, 35, 24, 31, 29],
    'Gaji': [8500000, 12000000, 7000000, 9500000, 11000000],
    'Rating': [4.5, 3.8, 4.2, 4.0, 4.7]
})

# Tambah kolom baru
karyawan['Gaji_Tahunan'] = karyawan['Gaji'] * 12

# Tambah kolom berdasarkan kondisi
import numpy as np
karyawan['Grade'] = np.where(karyawan['Rating'] >= 4.5, 'Top',
                    np.where(karyawan['Rating'] >= 4.0, 'Good', 'Average'))

# Hapus kolom
karyawan_baru = karyawan.drop(columns=['Gaji_Tahunan'])

# Rename kolom
karyawan_baru = karyawan_baru.rename(columns={'Rating': 'Skor_Kinerja'})

# Sort values
print(karyawan_baru.sort_values('Gaji', ascending=False))

# Tambah baris baru
new_row = pd.DataFrame([{
    'Nama': 'Fajar',
    'Departemen': 'IT',
    'Usia': 26,
    'Gaji': 7500000,
    'Skor_Kinerja': 4.3,
    'Grade': 'Good'
}])
karyawan_final = pd.concat([karyawan_baru, new_row], ignore_index=True)
print(karyawan_final)

Handling Missing Data

Python — Missing Data
import pandas as pd
import numpy as np

# DataFrame dengan missing values
df = pd.DataFrame({
    'Nama': ['Andi', 'Budi', 'Citra', 'Dewi', 'Eka'],
    'Usia': [28, np.nan, 24, 31, np.nan],
    'Gaji': [8500000, 12000000, np.nan, 9500000, 11000000],
    'Kota': ['Jakarta', 'Bandung', None, 'Surabaya', 'Medan']
})

# Cek missing values
print(df.isnull().sum())
# Nama    0
# Usia    2
# Gaji    1
# Kota    1

# Hapus baris dengan missing values
df_clean = df.dropna()

# Isi missing values
df_filled = df.copy()
df_filled['Usia'] = df_filled['Usia'].fillna(df_filled['Usia'].mean())
df_filled['Gaji'] = df_filled['Gaji'].fillna(df_filled['Gaji'].median())
df_filled['Kota'] = df_filled['Kota'].fillna('Tidak Diketahui')

print(df_filled)


6. Indexing & Filtering Data

Pandas menyediakan beberapa cara untuk mengakses dan memfilter data: loc (label-based), iloc (integer-based), dan boolean indexing.

loc vs iloc

Method Basis Slicing Contoh
.loc[]Label (nama kolom/index)Inklusif (termasuk stop)df.loc[0:2, 'Nama':'Gaji']
.iloc[]Integer positionEksklusif (tidak termasuk stop)df.iloc[0:3, 0:3]
Python — Indexing & Filtering
import pandas as pd

df = pd.DataFrame({
    'Nama': ['Andi', 'Budi', 'Citra', 'Dewi', 'Eka'],
    'Departemen': ['IT', 'Finance', 'IT', 'HR', 'Finance'],
    'Usia': [28, 35, 24, 31, 29],
    'Gaji': [8500000, 12000000, 7000000, 9500000, 11000000],
    'Rating': [4.5, 3.8, 4.2, 4.0, 4.7]
})

# loc — label-based
print(df.loc[0, 'Nama'])               # Andi
print(df.loc[0:2, ['Nama', 'Gaji']])   # Baris 0-2, kolom Nama & Gaji

# iloc — position-based
print(df.iloc[0, 0])                    # Andi (baris 0, kolom 0)
print(df.iloc[0:3, 0:3])               # Baris 0-2, kolom 0-2

# Boolean indexing (filtering)
# Karyawan dengan gaji > 9 juta
high_salary = df[df['Gaji'] > 9000000]
print(high_salary)

# Filter dengan multiple kondisi
# IT departemen DAN rating >= 4.0
it_top = df[(df['Departemen'] == 'IT') & (df['Rating'] >= 4.0)]
print(it_top)

# Filter dengan .isin()
target_dept = df[df['Departemen'].isin(['IT', 'HR'])]
print(target_dept)

# Filter dengan .str.contains()
# Cari nama yang mengandung huruf 'a'
names_with_a = df[df['Nama'].str.contains('a', case=False)]
print(names_with_a)

# .query() — sintaks yang lebih bersih
result = df.query('Departemen == "Finance" and Gaji > 10000000')
print(result)

# Set index
df_indexed = df.set_index('Nama')
print(df_indexed.loc['Andi'])  # Akses baris berdasarkan nama


7. GroupBy & Aggregasi

GroupBy adalah operasi split-apply-combine: membagi data berdasarkan kategori, menerapkan fungsi agregasi, lalu menggabungkan hasilnya. Ini sangat mirip dengan pivot table di Excel atau GROUP BY di SQL.

Diagram: Split-Apply-Combine
Group A
[10, 15]
Group B
[20, 25]
sum
GROUP BY (Split-Apply-Combine)
Original Data Split Apply Combine
A: 10
A: 25
B: 20
►
►B: 45
A: 15
B: 25
►
►
Python — GroupBy Operations
import pandas as pd
import numpy as np

# Dataset penjualan
np.random.seed(42)
penjualan = pd.DataFrame({
    'Tanggal': pd.date_range('2026-01-01', periods=20, freq='D'),
    'Produk': np.random.choice(['Laptop', 'HP', 'Tablet'], 20),
    'Kota': np.random.choice(['Jakarta', 'Bandung', 'Surabaya'], 20),
    'Jumlah': np.random.randint(1, 10, 20),
    'Harga_Satuan': np.random.choice([500000, 1000000, 800000], 20)
})

penjualan['Total'] = penjualan['Jumlah'] * penjualan['Harga_Satuan']

# GroupBy satu kolom
print("=== Total Penjualan per Produk ===")
produk_stats = penjualan.groupby('Produk')['Total'].agg([
    'sum', 'mean', 'count'
]).round(0)
print(produk_stats)

# GroupBy multiple kolom
print("\n=== Penjualan per Produk per Kota ===")
pivot = penjualan.groupby(['Kota', 'Produk'])['Total'].sum().unstack(fill_value=0)
print(pivot)

# Aggregasi dengan multiple fungsi
print("\n=== Statistik per Kota ===")
kota_agg = penjualan.groupby('Kota').agg({
    'Total': ['sum', 'mean', 'max'],
    'Jumlah': ['sum', 'mean'],
    'Produk': 'count'
})
print(kota_agg)

# Custom aggregation
print("\n=== Top Seller per Kota ===")
def top_product(group):
    return group.groupby('Produk')['Total'].sum().idxmax()

top = penjualan.groupby('Kota').apply(top_product)
print(top)

Pivot Table

Python — Pivot Table
# Pivot Table — seperti Excel pivot
pivot_table = pd.pivot_table(
    penjualan,
    values='Total',
    index='Kota',
    columns='Produk',
    aggfunc='sum',
    fill_value=0,
    margins=True,           # Tambahkan total
    margins_name='TOTAL'
)
print(pivot_table)

# Pivot dengan multiple aggregasi
pivot_multi = pd.pivot_table(
    penjualan,
    values='Total',
    index='Kota',
    columns='Produk',
    aggfunc=['sum', 'mean'],
    fill_value=0
)
print(pivot_multi)


8. Merge & Join Data

Merge dan Join memungkinkan Anda menggabungkan dua DataFrame berdasarkan kolom kunci yang sama — mirip dengan JOIN di SQL.

Jenis-Jenis Merge

Jenis Merge SQL Equivalent Penjelasan
innerINNER JOINHanya baris yang ada di kedua DataFrame
leftLEFT JOINSemua baris dari kiri + match dari kanan
rightRIGHT JOINSemua baris dari kanan + match dari kiri
outerFULL OUTER JOINSemua baris dari kedua DataFrame
███ █ █
█ █
███
███ █ █
███
Python — Merge & Join
import pandas as pd

# DataFrame 1: Pesanan
pesanan = pd.DataFrame({
    'order_id': [1, 2, 3, 4, 5],
    'customer_id': [101, 102, 103, 104, 105],
    'produk': ['Laptop', 'HP', 'Tablet', 'Laptop', 'HP'],
    'jumlah': [1, 2, 1, 3, 1]
})

# DataFrame 2: Pelanggan
pelanggan = pd.DataFrame({
    'customer_id': [101, 102, 103, 106, 107],
    'nama': ['Andi', 'Budi', 'Citra', 'Fajar', 'Gina'],
    'kota': ['Jakarta', 'Bandung', 'Surabaya', 'Medan', 'Semarang']
})

# Inner join (default)
inner = pd.merge(pesanan, pelanggan, on='customer_id', how='inner')
print("=== Inner Join ===")
print(inner)
# Hanya customer_id 101, 102, 103 yang muncul (ada di kedua tabel)

# Left join
left = pd.merge(pesanan, pelanggan, on='customer_id', how='left')
print("\n=== Left Join ===")
print(left)
# Semua pesanan ditampilkan, pelanggan yang tidak match = NaN

# Outer join
outer = pd.merge(pesanan, pelanggan, on='customer_id', how='outer')
print("\n=== Outer Join ===")
print(outer)
# Semua data dari kedua tabel

# Merge dengan kolom berbeda
orders_v2 = pesanan.rename(columns={'customer_id': 'cust_id'})
merged = pd.merge(orders_v2, pelanggan, left_on='cust_id', right_on='customer_id')
print(merged)

# Concat (menggabungkan baris)
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})
combined = pd.concat([df1, df2], ignore_index=True)
print(combined)
#    A  B
# 0  1  3
# 1  2  4
# 2  5  7
# 3  6  8


9. Export & Import Data

Pandas mendukung import dan export data ke berbagai format file. Berikut panduan lengkap untuk format yang paling sering digunakan:

Format yang Didukung

Format Read Write Kapan Digunakan
CSVpd.read_csv().to_csv()Data tabular umum, paling universal
Excelpd.read_excel().to_excel()Interoperabilitas dengan Excel
JSONpd.read_json().to_json()API, web, data terstruktur
SQLpd.read_sql().to_sql()Database MySQL/PostgreSQL/SQLite
Parquetpd.read_parquet().to_parquet()Data besar, Big Data (columnar)
Picklepd.read_pickle().to_pickle()Serialisasi Python (cepat, binary)
Python — Import & Export
import pandas as pd

# ========================
# CSV
# ========================
# Baca CSV
df = pd.read_csv('data.csv')

# Baca CSV dengan opsi
df = pd.read_csv(
    'data.csv',
    sep=',',                    # Separator (',' atau ';')
    encoding='utf-8',           # Encoding ('utf-8', 'latin-1')
    index_col=0,                # Kolom pertama sebagai index
    parse_dates=['tanggal'],    # Auto-parse kolom tanggal
    na_values=['N/A', '-', ''], # Nilai yang dianggap NaN
    thousands='.',              # Pemisah ribuan
    decimal=','                 # Pemisah desimal
)

# Simpan ke CSV
df.to_csv(
    'output.csv',
    index=False,          # Jangan simpan index
    encoding='utf-8',
    sep=','
)

# ========================
# EXCEL
# ========================
# Baca Excel
df_excel = pd.read_excel(
    'data.xlsx',
    sheet_name='Sheet1',   # Nama sheet
    header=0               # Baris header
)

# Simpan ke Excel
with pd.ExcelWriter('output.xlsx', engine='openpyxl') as writer:
    df.to_excel(writer, sheet_name='Data', index=False)
    df_excel.to_excel(writer, sheet_name='Lainnya', index=False)

# ========================
# JSON
# ========================
# Baca JSON
df_json = pd.read_json('data.json', orient='records')

# Simpan ke JSON
df.to_json('output.json', orient='records', indent=2, force_ascii=False)

# ========================
# SQL (SQLite contoh)
# ========================
import sqlite3
conn = sqlite3.connect('database.db')

# Baca dari SQL
df_sql = pd.read_sql('SELECT * FROM karyawan', conn)

# Tulis ke SQL
df.to_sql('karyawan_baru', conn, if_exists='replace', index=False)

conn.close()

# ========================
# PARQUET (format efisien untuk data besar)
# ========================
df.to_parquet('data.parquet', engine='pyarrow')
df_parquet = pd.read_parquet('data.parquet')
💡 Tips Format File
  • CSV — Gunakan untuk data kecil-sedang dan interoperabilitas
  • Parquet — Gunakan untuk data besar (100MB+): lebih cepat dan hemat storage
  • Pickle — Gunakan untuk serialisasi sementara (hanya Python, tidak aman)
  • JSON — Gunakan untuk data nested/hierarkis dan API


10. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Pandas & NumPy:

Pertanyaan 1: Apa perbedaan utama antara NumPy array dan Pandas DataFrame?

a) NumPy lebih lambat dari Pandas
b) NumPy array homogen (satu tipe), DataFrame heterogen (campur tipe)
c) Pandas tidak mendukung operasi matematika
d) NumPy hanya bisa 1 dimensi, Pandas hanya 2 dimensi

Pertanyaan 2: Apa yang dimaksud dengan "Broadcasting" dalam NumPy?

a) Mengirim data ke server lain
b) Mekanisme operasi antara array dengan ukuran berbeda tanpa menyalin data
c) Menampilkan array ke layar
d) Mengcopy array ke clipboard

Pertanyaan 3: Perbedaan antara .loc[] dan .iloc[] adalah?

a) loc untuk baris, iloc untuk kolom
b) loc berdasarkan label, iloc berdasarkan posisi integer
c) loc lebih cepat dari iloc
d) Tidak ada perbedaan, keduanya sama

Pertanyaan 4: Method apa yang digunakan untuk menggabungkan dua DataFrame berdasarkan kolom kunci (seperti SQL JOIN)?

a) df.append()
b) df.concat()
c) pd.merge()
d) df.join_column()

Pertanyaan 5: Format file apa yang paling efisien untuk menyimpan dataset besar (100MB+) dalam Pandas?

a) CSV
b) Excel (.xlsx)
c) JSON
d) Parquet
🔍 Zoom
100%
🎨 Tema