TL;DR
EDA itu langkah pertama sebelum analisis apapun. Pake SQL buat cek struktur data, summary statistics, missing values, distribusi, outliers, dan time patterns. Template EDA yang reusable bakal bikin hidup kamu lebih gampang.
Apa Itu EDA dan Kenapa Penting?
"Kenal dulu, baru analisis."
Itu prinsip dasar Exploratory Data Analysis (EDA). Sebelum kamu bikin model, dashboard, atau insight apapun, kamu harus kenal dulu sama datanya.
EDA itu proses investigasi awal untuk memahami karakteristik data. Kamu bakal nyari jawaban dari pertanyaan kayak:
- Data ini strukturnya gimana?
- Ada berapa banyak records?
- Missing values-nya banyak ga?
- Distribusinya kayak gimana?
- Ada outliers aneh ga?
Kenapa ini penting banget? Karena tanpa EDA, kamu bisa:
- Bikin kesimpulan yang salah
- Miss insight penting
- Buang waktu debug error yang harusnya bisa dihindari
Di bawah ada template EDA lengkap yang bisa langsung kamu pake untuk project apapun.
Apa yang Akan Kamu Pelajari
- [ ] Step 1: Mengenal struktur data
- [ ] Step 2: Summary statistics
- [ ] Step 3: Cek missing values dan completeness
- [ ] Step 4: Distribusi data
- [ ] Step 5: Cek outliers
- [ ] Step 6: Cardinality check
- [ ] Step 7: Korelasi antar variabel
- [ ] Step 8: Time-series patterns
- [ ] Template EDA yang reusable
Dataset yang Akan Kita Pakai
Ceritanya kamu baru gabung sebagai Data Analyst di startup e-commerce Indonesia. Kamu dapet akses ke database dan diminta untuk "explore" data transaksi.
Tabel: orders
| order_id | customer_id | order_date | product_category | quantity | unit_price | total_amount | payment_method | status | city |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 101 | 2024-01-15 | Elektronik | 1 | 2500000 | 2500000 | credit_card | completed | Jakarta |
| 2 | 102 | 2024-01-15 | Fashion | 3 | 150000 | 450000 | bank_transfer | completed | Bandung |
| 3 | 103 | 2024-01-16 | Elektronik | 2 | 500000 | 1000000 | e_wallet | completed | Surabaya |
| 4 | 101 | 2024-01-17 | Makanan | 5 | 25000 | 125000 | cod | cancelled | Jakarta |
| 5 | 104 | 2024-01-18 | Fashion | NULL | 200000 | 400000 | credit_card | completed | NULL |
| 6 | 105 | 2024-01-19 | Elektronik | 1 | 15000000 | 15000000 | credit_card | completed | Medan |
| 7 | 102 | 2024-01-20 | Makanan | 10 | 15000 | 150000 | e_wallet | pending | Bandung |
| 8 | 106 | 2024-01-21 | Fashion | 2 | 300000 | 600000 | bank_transfer | completed | Jakarta |
| 9 | NULL | 2024-01-22 | Elektronik | 1 | 8000000 | 8000000 | credit_card | completed | Surabaya |
| 10 | 107 | 2024-01-23 | Beauty | 4 | 75000 | 300000 | e_wallet | completed | Semarang |
Data ini sengaja dibikin "kotor" biar lebih realistis.
Step 1: Mengenal Struktur Data
Cek Jumlah Total Records
SELECT COUNT(*) AS total_records
FROM orders;
Hasil:
| total_records |
|---|
| 10 |
Cek Kolom dan Tipe Data (PostgreSQL)
SELECT
column_name,
data_type,
is_nullable,
column_default
FROM information_schema.columns
WHERE table_name = 'orders'
ORDER BY ordinal_position;
Quick Sample Data
SELECT *
FROM orders
LIMIT 5;
Selalu liat sample data dulu. Kadang ada anomali yang langsung keliatan dari sample.
Cek Range Tanggal
SELECT
MIN(order_date) AS earliest_date,
MAX(order_date) AS latest_date,
MAX(order_date) - MIN(order_date) AS date_range_days,
COUNT(DISTINCT DATE(order_date)) AS unique_dates
FROM orders;
Hasil:
| earliest_date | latest_date | date_range_days | unique_dates |
|---|---|---|---|
| 2024-01-15 | 2024-01-23 | 8 | 9 |
Data spanning 8 hari dengan 9 tanggal unik.
Step 2: Summary Statistics
Numeric Columns
SELECT
'quantity' AS column_name,
COUNT(*) AS total,
COUNT(quantity) AS non_null,
COUNT(*) - COUNT(quantity) AS null_count,
ROUND(AVG(quantity), 2) AS mean,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY quantity) AS median,
MODE() WITHIN GROUP (ORDER BY quantity) AS mode,
MIN(quantity) AS min,
MAX(quantity) AS max,
ROUND(STDDEV(quantity), 2) AS std_dev
FROM orders
UNION ALL
SELECT
'unit_price',
COUNT(*),
COUNT(unit_price),
COUNT(*) - COUNT(unit_price),
ROUND(AVG(unit_price), 2),
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY unit_price),
MODE() WITHIN GROUP (ORDER BY unit_price),
MIN(unit_price),
MAX(unit_price),
ROUND(STDDEV(unit_price), 2)
FROM orders
UNION ALL
SELECT
'total_amount',
COUNT(*),
COUNT(total_amount),
COUNT(*) - COUNT(total_amount),
ROUND(AVG(total_amount), 2),
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY total_amount),
MODE() WITHIN GROUP (ORDER BY total_amount),
MIN(total_amount),
MAX(total_amount),
ROUND(STDDEV(total_amount), 2)
FROM orders;
Hasil:
| column_name | total | non_null | null_count | mean | median | mode | min | max | std_dev |
|---|---|---|---|---|---|---|---|---|---|
| quantity | 10 | 9 | 1 | 3.22 | 2 | 1 | 1 | 10 | 2.91 |
| unit_price | 10 | 10 | 0 | 2681500 | 275000 | 200000 | 15000 | 15000000 | 4712345.67 |
| total_amount | 10 | 10 | 0 | 2852500 | 525000 | 400000 | 125000 | 15000000 | 4654321.89 |
Insight:
- Ada 1 NULL di quantity
- unit_price range-nya gede banget (15rb - 15jt), standard deviation tinggi
- Mean jauh dari median = distribusi skewed
Step 3: Cek Missing Values
Missing Value Count per Kolom
SELECT
COUNT(*) AS total_rows,
COUNT(*) - COUNT(order_id) AS null_order_id,
COUNT(*) - COUNT(customer_id) AS null_customer_id,
COUNT(*) - COUNT(order_date) AS null_order_date,
COUNT(*) - COUNT(product_category) AS null_category,
COUNT(*) - COUNT(quantity) AS null_quantity,
COUNT(*) - COUNT(unit_price) AS null_unit_price,
COUNT(*) - COUNT(total_amount) AS null_total,
COUNT(*) - COUNT(payment_method) AS null_payment,
COUNT(*) - COUNT(status) AS null_status,
COUNT(*) - COUNT(city) AS null_city
FROM orders;
Hasil:
| total_rows | null_order_id | null_customer_id | null_order_date | null_category | null_quantity | null_unit_price | null_total | null_payment | null_status | null_city |
|---|---|---|---|---|---|---|---|---|---|---|
| 10 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
Insight: Ada missing values di customer_id, quantity, dan city.
Missing Value Percentage
SELECT
ROUND(100.0 * (COUNT(*) - COUNT(customer_id)) / COUNT(*), 2) AS pct_null_customer_id,
ROUND(100.0 * (COUNT(*) - COUNT(quantity)) / COUNT(*), 2) AS pct_null_quantity,
ROUND(100.0 * (COUNT(*) - COUNT(city)) / COUNT(*), 2) AS pct_null_city
FROM orders;
Hasil:
| pct_null_customer_id | pct_null_quantity | pct_null_city |
|---|---|---|
| 10.00 | 10.00 | 10.00 |
10% missing rate cukup tinggi, perlu diinvestigasi.
Rows with Any NULL
SELECT *
FROM orders
WHERE customer_id IS NULL
OR quantity IS NULL
OR city IS NULL;
Step 4: Distribusi Data
Categorical Columns Distribution
-- Product Category Distribution
SELECT
product_category,
COUNT(*) AS count,
ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 2) AS percentage
FROM orders
GROUP BY product_category
ORDER BY count DESC;
Hasil:
| product_category | count | percentage |
|---|---|---|
| Elektronik | 4 | 40.00 |
| Fashion | 3 | 30.00 |
| Makanan | 2 | 20.00 |
| Beauty | 1 | 10.00 |
-- Payment Method Distribution
SELECT
payment_method,
COUNT(*) AS count,
ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 2) AS percentage
FROM orders
GROUP BY payment_method
ORDER BY count DESC;
Hasil:
| payment_method | count | percentage |
|---|---|---|
| credit_card | 4 | 40.00 |
| e_wallet | 3 | 30.00 |
| bank_transfer | 2 | 20.00 |
| cod | 1 | 10.00 |
-- Status Distribution
SELECT
status,
COUNT(*) AS count,
ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 2) AS percentage
FROM orders
GROUP BY status
ORDER BY count DESC;
Hasil:
| status | count | percentage |
|---|---|---|
| completed | 8 | 80.00 |
| pending | 1 | 10.00 |
| cancelled | 1 | 10.00 |
Numeric Distribution (Histogram Buckets)
WITH buckets AS (
SELECT
CASE
WHEN total_amount < 500000 THEN '< 500K'
WHEN total_amount < 1000000 THEN '500K - 1M'
WHEN total_amount < 5000000 THEN '1M - 5M'
WHEN total_amount < 10000000 THEN '5M - 10M'
ELSE '>= 10M'
END AS amount_bucket,
CASE
WHEN total_amount < 500000 THEN 1
WHEN total_amount < 1000000 THEN 2
WHEN total_amount < 5000000 THEN 3
WHEN total_amount < 10000000 THEN 4
ELSE 5
END AS bucket_order
FROM orders
)
SELECT
amount_bucket,
COUNT(*) AS count,
REPEAT('█', COUNT(*)) AS visual
FROM buckets
GROUP BY amount_bucket, bucket_order
ORDER BY bucket_order;
Hasil:
| amount_bucket | count | visual |
|---|---|---|
| < 500K | 4 | ████ |
| 500K - 1M | 2 | ██ |
| 1M - 5M | 1 | █ |
| 5M - 10M | 1 | █ |
| >= 10M | 2 | ██ |
Kebanyakan transaksi di bawah 500K, tapi ada beberapa high-value transactions.
Step 5: Cek Outliers
Statistik untuk Deteksi Outliers
WITH stats AS (
SELECT
PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY total_amount) AS q1,
PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY total_amount) AS median,
PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY total_amount) AS q3
FROM orders
)
SELECT
q1,
median,
q3,
q3 - q1 AS iqr,
q1 - 1.5 * (q3 - q1) AS lower_bound,
q3 + 1.5 * (q3 - q1) AS upper_bound
FROM stats;
Identifikasi Outliers
WITH stats AS (
SELECT
PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY total_amount) AS q1,
PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY total_amount) AS q3
FROM orders
)
SELECT
o.*,
CASE
WHEN o.total_amount < (s.q1 - 1.5 * (s.q3 - s.q1)) THEN 'Low Outlier'
WHEN o.total_amount > (s.q3 + 1.5 * (s.q3 - s.q1)) THEN 'High Outlier'
ELSE 'Normal'
END AS outlier_status
FROM orders o
CROSS JOIN stats s
WHERE o.total_amount < (s.q1 - 1.5 * (s.q3 - s.q1))
OR o.total_amount > (s.q3 + 1.5 * (s.q3 - s.q1));
Cek Nilai Extreme
-- Top 5 highest
SELECT order_id, customer_id, total_amount, product_category
FROM orders
ORDER BY total_amount DESC
LIMIT 5;
-- Top 5 lowest
SELECT order_id, customer_id, total_amount, product_category
FROM orders
ORDER BY total_amount ASC
LIMIT 5;
Step 6: Cardinality Check
Cardinality = jumlah nilai unik dalam kolom.
SELECT
COUNT(DISTINCT order_id) AS unique_order_id,
COUNT(DISTINCT customer_id) AS unique_customers,
COUNT(DISTINCT product_category) AS unique_categories,
COUNT(DISTINCT payment_method) AS unique_payment_methods,
COUNT(DISTINCT status) AS unique_status,
COUNT(DISTINCT city) AS unique_cities,
COUNT(DISTINCT DATE(order_date)) AS unique_dates
FROM orders;
Hasil:
| unique_order_id | unique_customers | unique_categories | unique_payment_methods | unique_status | unique_cities | unique_dates |
|---|---|---|---|---|---|---|
| 10 | 7 | 4 | 4 | 3 | 5 | 9 |
Insight:
- 10 orders dari 7 unique customers (ada repeat buyers)
- 4 kategori, 4 payment methods, 3 status
- 5 kota berbeda
High Cardinality Check
Untuk kolom yang harusnya low cardinality tapi ternyata high:
SELECT
city,
COUNT(*) AS count
FROM orders
WHERE city IS NOT NULL
GROUP BY city
ORDER BY city;
Cek apakah ada typo atau variasi penulisan (misalnya "Jakarta" vs "JAKARTA" vs "Jkt").
Step 7: Korelasi Antar Variabel
Cross-tabulation (Kategori vs Kategori)
SELECT
product_category,
COUNT(CASE WHEN status = 'completed' THEN 1 END) AS completed,
COUNT(CASE WHEN status = 'pending' THEN 1 END) AS pending,
COUNT(CASE WHEN status = 'cancelled' THEN 1 END) AS cancelled
FROM orders
GROUP BY product_category
ORDER BY product_category;
Hasil:
| product_category | completed | pending | cancelled |
|---|---|---|---|
| Beauty | 1 | 0 | 0 |
| Elektronik | 4 | 0 | 0 |
| Fashion | 2 | 0 | 0 |
| Makanan | 1 | 1 | 1 |
Insight: Makanan punya rate cancelled dan pending yang tinggi relatif terhadap total order-nya.
Numeric by Category
SELECT
product_category,
COUNT(*) AS total_orders,
ROUND(AVG(total_amount), 0) AS avg_amount,
ROUND(AVG(quantity), 1) AS avg_quantity
FROM orders
WHERE quantity IS NOT NULL
GROUP BY product_category
ORDER BY avg_amount DESC;
Hasil:
| product_category | total_orders | avg_amount | avg_quantity |
|---|---|---|---|
| Elektronik | 4 | 6625000 | 1.3 |
| Fashion | 3 | 483333 | 2.5 |
| Beauty | 1 | 300000 | 4.0 |
| Makanan | 2 | 137500 | 7.5 |
Insight: Elektronik = high value, low quantity. Makanan = low value, high quantity.
Step 8: Time-Series Patterns
Daily Trends
SELECT
DATE(order_date) AS date,
COUNT(*) AS order_count,
SUM(total_amount) AS daily_revenue,
ROUND(AVG(total_amount), 0) AS avg_order_value
FROM orders
GROUP BY DATE(order_date)
ORDER BY date;
Hasil:
| date | order_count | daily_revenue | avg_order_value |
|---|---|---|---|
| 2024-01-15 | 2 | 2950000 | 1475000 |
| 2024-01-16 | 1 | 1000000 | 1000000 |
| 2024-01-17 | 1 | 125000 | 125000 |
| 2024-01-18 | 1 | 400000 | 400000 |
| 2024-01-19 | 1 | 15000000 | 15000000 |
| 2024-01-20 | 1 | 150000 | 150000 |
| 2024-01-21 | 1 | 600000 | 600000 |
| 2024-01-22 | 1 | 8000000 | 8000000 |
| 2024-01-23 | 1 | 300000 | 300000 |
Day of Week Pattern
SELECT
EXTRACT(DOW FROM order_date) AS day_of_week,
CASE EXTRACT(DOW FROM order_date)
WHEN 0 THEN 'Minggu'
WHEN 1 THEN 'Senin'
WHEN 2 THEN 'Selasa'
WHEN 3 THEN 'Rabu'
WHEN 4 THEN 'Kamis'
WHEN 5 THEN 'Jumat'
WHEN 6 THEN 'Sabtu'
END AS day_name,
COUNT(*) AS order_count,
SUM(total_amount) AS total_revenue
FROM orders
GROUP BY EXTRACT(DOW FROM order_date)
ORDER BY day_of_week;
Growth Trend
WITH daily AS (
SELECT
DATE(order_date) AS date,
COUNT(*) AS orders,
SUM(total_amount) AS revenue
FROM orders
GROUP BY DATE(order_date)
)
SELECT
date,
orders,
revenue,
LAG(orders) OVER (ORDER BY date) AS prev_orders,
LAG(revenue) OVER (ORDER BY date) AS prev_revenue,
orders - LAG(orders) OVER (ORDER BY date) AS order_change,
revenue - LAG(revenue) OVER (ORDER BY date) AS revenue_change
FROM daily
ORDER BY date;
Template EDA yang Reusable
Copy paste template ini dan ganti nama tabel/kolom sesuai kebutuhan:
-- =============================================
-- EDA TEMPLATE
-- Ganti 'your_table' dan nama kolom sesuai data kamu
-- =============================================
-- 1. BASIC INFO
SELECT
'Total Records' AS metric,
COUNT(*)::TEXT AS value
FROM your_table
UNION ALL
SELECT
'Date Range',
MIN(date_column)::TEXT || ' to ' || MAX(date_column)::TEXT
FROM your_table
UNION ALL
SELECT
'Unique Primary Key',
COUNT(DISTINCT primary_key_column)::TEXT
FROM your_table;
-- 2. MISSING VALUES
SELECT
'Column Name' AS column_name,
COUNT(*) AS total,
COUNT(column_name) AS non_null,
COUNT(*) - COUNT(column_name) AS null_count,
ROUND(100.0 * (COUNT(*) - COUNT(column_name)) / COUNT(*), 2) AS null_pct
FROM your_table;
-- 3. NUMERIC SUMMARY
SELECT
'numeric_column' AS column_name,
COUNT(*) AS count,
ROUND(AVG(numeric_column), 2) AS mean,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY numeric_column) AS median,
MIN(numeric_column) AS min,
MAX(numeric_column) AS max,
ROUND(STDDEV(numeric_column), 2) AS std_dev
FROM your_table;
-- 4. CATEGORICAL DISTRIBUTION
SELECT
categorical_column,
COUNT(*) AS count,
ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 2) AS percentage
FROM your_table
GROUP BY categorical_column
ORDER BY count DESC;
-- 5. CARDINALITY
SELECT
COUNT(DISTINCT column1) AS unique_col1,
COUNT(DISTINCT column2) AS unique_col2,
COUNT(DISTINCT column3) AS unique_col3
FROM your_table;
-- 6. TIME PATTERNS
SELECT
DATE_TRUNC('day', date_column) AS date,
COUNT(*) AS count,
SUM(amount_column) AS total
FROM your_table
GROUP BY DATE_TRUNC('day', date_column)
ORDER BY date;
Common Mistakes yang Harus Dihindari
Mistake 1: Skip EDA, Langsung Analisis
-- LANGSUNG bikin dashboard tanpa EDA
SELECT category, SUM(amount) FROM orders GROUP BY category;
-- Tapi ga tau ada NULL, outliers, atau data quality issues
Selalu EDA dulu!
Mistake 2: Ignore Missing Values
-- NULL di-ignore, hasilnya bisa misleading
SELECT AVG(quantity) FROM orders; -- NULL ga dihitung
Mistake 3: Ga Cek Outliers
Satu transaksi 15 juta bisa skew average dari 500rb jadi 2.8 juta.
Mistake 4: Assume Data Quality
Jangan assume. Verify!
Dokumentasi Findings
Setelah EDA, selalu dokumentasikan findings:
## EDA Summary: Orders Table
### Overview
- Total records: 10
- Date range: 2024-01-15 to 2024-01-23
- Unique customers: 7
### Data Quality Issues
1. Missing customer_id: 10% (1 record)
2. Missing quantity: 10% (1 record)
3. Missing city: 10% (1 record)
### Key Distributions
- Product Category: Elektronik (40%), Fashion (30%), Makanan (20%), Beauty (10%)
- Payment: Credit Card (40%), E-Wallet (30%), Bank Transfer (20%), COD (10%)
- Status: Completed (80%), Pending (10%), Cancelled (10%)
### Outliers
- High value transactions: Order #6 (15M), Order #9 (8M)
- These are valid (Elektronik category)
### Recommendations
1. Investigate missing customer_id on order #9
2. High cancellation rate on Makanan category needs attention
3. Consider capping outliers for aggregate analysis
Latihan
Soal: Lakukan EDA lengkap pada tabel orders dan jawab:
1. Berapa completion rate overall?
2. Payment method mana yang punya highest average order value?
3. Ada anomali apa yang perlu diinvestigasi?
Klik untuk lihat solusi
-- 1. Completion Rate
SELECT
ROUND(100.0 * COUNT(CASE WHEN status = 'completed' THEN 1 END) / COUNT(*), 2) AS completion_rate
FROM orders;
-- Hasil: 80%
-- 2. AOV by Payment Method
SELECT
payment_method,
COUNT(*) AS orders,
ROUND(AVG(total_amount), 0) AS avg_order_value
FROM orders
GROUP BY payment_method
ORDER BY avg_order_value DESC;
-- Hasil: credit_card punya highest AOV
-- 3. Anomali
-- a) Order #9 ga punya customer_id
-- b) Order #5 ga punya quantity dan city
-- c) Makanan punya cancellation rate 50%
SELECT * FROM orders WHERE customer_id IS NULL OR quantity IS NULL;
FAQ
Apa bedanya EDA pakai SQL sama pakai Python?
Python (pandas) lebih enak buat visualisasi dan analisis statistik lanjutan. Tapi SQL jalan langsung di database — kamu nggak perlu export data dulu. Buat dataset jutaan baris, SQL jauh lebih cepat soalnya komputasinya di server, bukan di laptop kamu. Praktiknya banyak analyst pakai dua-duanya: SQL buat first pass, Python buat deep dive. Template di artikel ini udah cukup buat 80% kebutuhan EDA harian kok.
Query di artikel ini jalan di MySQL nggak?
Sebagian besar jalan. Yang perlu disesuaikan: PERCENTILE_CONT dan MODE() itu fitur PostgreSQL — di MySQL kamu bisa pakai window function (MySQL 8+) atau kombinasi ORDER BY dan LIMIT buat cari median. information_schema.columns sama-sama ada di MySQL. Sisanya kayak COUNT, GROUP BY, dan CASE itu standar SQL, jalan di mana aja.
Berapa lama idealnya ngerjain EDA?
Tergantung ukuran datanya. Buat satu tabel kayak contoh di atas, 30-60 menit udah cukup buat jalanin 8 step ini. Dataset dengan 10+ tabel bisa makan 1-2 hari. Patokannya gini: berhenti kalau kamu udah bisa jawab struktur, kualitas, distribusi, dan anomali datanya. EDA kelamaan tanpa arah itu procrastination terselubung lho.
Kalau nemu missing values, harus diapain?
Jangan langsung dihapus atau diisi. Investigasi dulu kenapa bisa kosong — bug di aplikasi, data lama, atau memang field opsional? Kalau missing rate di bawah 5% dan polanya random, biasanya aman di-exclude. Kalau polanya sistematis, misalnya semua NULL datang dari satu payment method, itu sinyal masalah di pipeline datanya. Detailnya ada di artikel data cleaning.
Kesimpulan
EDA itu langkah pertama dari setiap analisis yang bener. Inget poin-poin ini:
- Selalu mulai dengan EDA sebelum analisis apapun
- Cek struktur data: rows, columns, data types
- Hitung summary statistics: mean, median, min, max
- Identifikasi missing values dan persentasenya
- Pahami distribusi categorical dan numeric
- Deteksi outliers yang bisa skew analisis
- Check cardinality untuk potensi data quality issues
- Explore time patterns kalau ada date column
- Dokumentasikan semua findings
Template EDA yang reusable bakal bikin hidup kamu lebih gampang. Invest time di awal, save time later!
Happy exploring!
Selanjutnya
Kalau kamu udah paham EDA, next step-nya:
- Data Cleaning - bersihin data yang kotor
- Funnel Analysis - analisis conversion
- Cohort Analysis - analisis retention
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel Terkait
Membuat Dashboard Metrics dengan SQL: KPI yang Wajib Ditrack
Panduan lengkap query SQL untuk membangun dashboard metrics, dari revenue metrics sampai retention analysis.
Funnel Analysis dengan SQL: Mengukur Conversion Rate Step-by-Step
Pelajari cara bikin funnel analysis untuk mengukur conversion rate di setiap step. Lengkap dengan template query dan cara present ke stakeholder.
SQL untuk A/B Testing Analysis: Panduan Praktis
Pelajari cara menganalisis A/B test dengan SQL. Dari hitung conversion rate sampai statistical significance dengan contoh e-commerce Indonesia.