Data Transformation
Assignment ~ Week 9
Arya Fharezi
NIM Mahasiswa : 522500081 Transformasi Temporal
Lag, Diff, dan Rolling Mean
Perhatikan kode R berikut yang melakukan transformasi temporal pada
dataset data_bisnis menggunakan fungsi lag(),
diff, dan rolling mean (library zoo).
Mengapa kolom Lag_Quantity, Diff_Quantity, dan
RollingMean_3 pada output menampilkan nilai NA? Jelaskan!
1.1 Kode & Output
# Load data
data_bisnis <- read.csv("6_Data-Transformation___Data_Science_Programming.csv")
library(knitr)
# (Contoh untuk Quantity, berdasarkan tanggal transaksi)
Tempral <- data_bisnis %>%
arrange(Customer_ID, Transaction_Date) %>%
group_by(Customer_ID) %>%
mutate(
Lag_Quantity = lag(Quantity),
Diff_Quantity = Quantity - lag(Quantity),
RollingMean_3 = zoo::rollapply(Quantity, width = 3,
FUN = mean, fill = NA, align = 'right')
) %>%
ungroup()
# Tampilkan 5 baris pertama
kable(head(Tempral, 5))| X | Transaction_ID | Transaction_Date | Customer_ID | Product_Category | Product_ID | Quantity | Unit_Price | Discount | Region | Sales_Channel | Delivery_Time | Total_Price | Price_per_Unit | Efficiency | Feature_Interaction | Cross_Term | ID_Prefix | ID_Length | ID_HasPattern | Discount_Level | Sales_Rank | Avg_Quantity_Region | Sum_Sales_Region | Count_Product_Region | Lag_Quantity | Diff_Quantity | RollingMean_3 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 122 | 1PaWvGiAokHB | 2023-02-09 | 02kNipUny9 | Groceries | P0253 | 3 | 13.11 | 0.07 | East | Offline | 10 | 36.58 | 12.193333 | 0.300 | 0.21 | Groceries_East | P0 | 5 | true | 2 | 208 | 2.936508 | 4261.13 | 126 | NA | NA | NA |
| 400 | IYlg0MAGwsUw | 2020-11-30 | 04npfK5VJa | Books | P0113 | 3 | 15.90 | 0.24 | North | Offline | 3 | 36.25 | 12.083333 | 1.000 | 0.72 | Books_North | P0 | 5 | true | 4 | 212 | 2.992908 | 4864.94 | 141 | NA | NA | NA |
| 201 | 0kgKWZOpEp6Z | 2020-03-18 | 0NwgTyo7P2 | Clothing | P0445 | 5 | 2.65 | 0.20 | North | Offline | 8 | 10.60 | 2.120000 | 0.625 | 1.00 | Clothing_North | P0 | 5 | true | 3 | 425 | 2.992908 | 4864.94 | 141 | NA | NA | NA |
| 412 | ddFsMFlQOa2J | 2023-05-19 | 0PlvCaxPuS | Electronics | P0298 | 3 | 9.12 | 0.20 | East | Online | 8 | 21.89 | 7.296667 | 0.375 | 0.60 | Electronics_East | P0 | 5 | true | 3 | 335 | 2.936508 | 4261.13 | 126 | NA | NA | NA |
| 300 | VOCzzxDOxQps | 2020-07-07 | 0S9qOEuCr9 | Clothing | P0353 | 3 | 1.31 | 0.12 | West | Online | 2 | 3.46 | 1.153333 | 1.500 | 0.36 | Clothing_West | P0 | 5 | true | 2 | 469 | 3.116667 | 4169.72 | 120 | NA | NA | NA |
1.2 Jawaban:
Analisis Kemunculan Nilai NA (Not Available)
Nilai NA (Not Available) dalam R muncul ketika suatu nilai tidak tersedia atau tidak bisa dihitung. Pada kasus ini, munculnya NA di ketiga kolom bukan berarti kodenya salah, tapi memang begitulah cara kerja fungsi-fungsi transformasi temporal yang digunakan.
Sebelum masuk ke penjelasan tiap kolom, berikut konteks kode yang relevan dengan munculnya NA:
-
arrange(Customer_ID, Transaction_Date)— Mengurutkan data berdasarkan Customer_ID lalu Transaction_Date, hal ini penting karena fungsilag()danrollapply()sangat bergantung pada urutan baris. Jika urutan salah, nilai NA bisa muncul di posisi yang tidak tepat. -
group_by(Customer_ID)— Mengelompokkan per customer. Inilah penyebab utama NA muncul di baris pertama setiap customer, karena setiap grup selalu mulai dari awal tanpa riwayat data sebelumnya.
1. Kolom Lag_Quantity = lag(Quantity)
a. Definisi Fungsi lag()
Fungsi lag() dari paket dplyr bekerja dengan cara mengambil
nilai dari baris sebelumnya dalam suatu urutan data. Sederhananya,
nilai-nilai tersebut digeser ke bawah sebanyak n langkah, dengan default
n = 1.
Rumus Konseptual:
Lag_Quantity[baris ke-n] =
Quantity[baris ke-(n-1)]
Contoh sederhana (tanpa
pengelompokan):
Quantity : 5 8 3 7
Lag_Quantity :
NA 5 8 3
b. Pengaruh group_by(Customer_ID)
Karena kode menggunakan group_by(Customer_ID) sebelum
mutate(), setiap Customer_ID dihitung secara terpisah.
Artinya setiap kali berpindah ke Customer_ID baru, fungsi
lag() mulai dari awal lagi tanpa mengambil nilai dari
customer sebelumnya. Akibatnya, baris pertama dari setiap
Customer_ID akan selalu NA karena tidak ada baris sebelumnya
dalam kelompok tersebut.
2. Kolom Diff_Quantity = Quantity - lag(Quantity)
a. Definisi Operasi
Kolom Diff_Quantity berisi hasil pengurangan antara nilai
Quantity saat ini dengan Lag_Quantity atau Quantity baris sebelumnya.
Kolom ini digunakan untuk melihat selisih perubahan antar transaksi yang
berurutan pada customer yang sama.
Hukum Propagasi NA dalam R:
angka + NA = NA
angka - NA = NA
angka * NA = NA
Contoh: 5 - NA = NA | 10 -
NA = NA
b. Alur Terjadinya NA
Karena Lag_Quantity di baris pertama setiap Customer_ID
bernilai NA, maka Quantity - NA otomatis menghasilkan NA
juga. Diff_Quantity tidak bisa dihitung karena salah satu nilainya yaitu
Lag_Quantity tidak tersedia.
3. Kolom RollingMean_3 = zoo::rollapply(…, width=3)
a. Definisi Fungsi rollapply()
Fungsi zoo::rollapply() menerapkan suatu fungsi pada window
atau jendela data yang bergerak dengan lebar tertentu. Dalam kasus ini
fungsi yang dipakai adalah mean, sehingga menghasilkan Rolling Mean
yaitu rata-rata dari sejumlah n data terakhir yang terus bergerak
seiring berjalannya waktu.
Parameter Penting dalam Kode:
width = 3 #
Jendela data yang digunakan berjumlah 3 baris berturut-turut
FUN =
mean # Fungsi yang diterapkan adalah rata-rata aritmatika
fill = NA
# Posisi yang tidak dapat dihitung diisi dengan nilai NA
align =
‘right’ # Window dihitung dari sisi kanan (data saat ini + 2
sebelumnya)
b. Mekanisme Rolling Window
Dengan align=‘right’ dan width=3, fungsi ini
butuh data dari baris sekarang dan dua baris sebelumnya untuk bisa
melakukan perhitungan. Kalau datanya belum cukup, nilainya akan diisi NA
sesuai parameter fill=NA yang sudah diset di kode.
| Baris | Qty[n-2] | Qty[n-1] | Qty[n] | Penjelasan | Hasil |
|---|---|---|---|---|---|
| 1 (pertama) | - | - | 5 | Hanya 1 data tersedia, butuh 3 | NA |
| 2 | - | 5 | 8 | Hanya 2 data tersedia, butuh 3 | NA |
| 3 | 5 | 8 | 3 | Sudah 3 data: (5+8+3)/3 | 5.33 ✓ |
| 4 | 8 | 3 | 7 | Sudah 3 data: (8+3+7)/3 | 6.00 ✓ |
Keterangan: Warna kuning = NA (belum tersedia cukup data) | Warna hijau = berhasil dihitung
c. Pengaruh group_by(Customer_ID)
Sama seperti lag(), fungsi rollapply() juga
dipengaruhi oleh group_by(Customer_ID). Setiap customer
punya urutannya sendiri, sehingga rolling window tidak bisa mengambil
data dari customer lain. Akibatnya, 2 baris pertama setiap
Customer_ID selalu menghasilkan NA.
Semua NA yang muncul pada ketiga kolom tersebut terjadi karena fungsi-fungsi temporal yang digunakan membutuhkan data historis sebelumnya, sementara pengelompokan per Customer_ID membuat setiap grup selalu mulai dari awal tanpa riwayat data apapun.
Lag_Quantity
NA di baris ke-1 tiap customer
Diff_Quantity
NA di baris ke-1 tiap customer
RollingMean_3
NA di baris ke-1 & ke-2 tiap
customer
2 Log Transform (log1p)
Pertanyaan: Jelaskan tentang log1p pada
kode berikut.
2.1 Kode & Output
min_positive <- min(data_bisnis$Total_Price[data_bisnis$Total_Price > 0])
Log <- data_bisnis %>%
mutate(
Safe_Total_Price = ifelse(Total_Price <= 0, min_positive, Total_Price),
Log_Total_Price = log1p(Safe_Total_Price)
)
# Tampilkan 5 baris pertama
kable(head(Log, 5))| X | Transaction_ID | Transaction_Date | Customer_ID | Product_Category | Product_ID | Quantity | Unit_Price | Discount | Region | Sales_Channel | Delivery_Time | Total_Price | Price_per_Unit | Efficiency | Feature_Interaction | Cross_Term | ID_Prefix | ID_Length | ID_HasPattern | Discount_Level | Sales_Rank | Avg_Quantity_Region | Sum_Sales_Region | Count_Product_Region | Safe_Total_Price | Log_Total_Price |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 7zmPHxF7XfN9 | 2021-07-14 | BAl3Y7yxev | Clothing | P0370 | 2 | 15.18 | 0.00 | North | Online | 5 | 30.36 | 15.18000 | 0.4000000 | 0.00 | Clothing_North | P0 | 5 | true | 1 | 253 | 2.992908 | 4864.94 | 141 | 30.36 | 3.445533 |
| 2 | y4bCY9pKTBWU | 2020-11-16 | TYY0h5C190 | Electronics | P0185 | 5 | 10.22 | 0.15 | West | Offline | 2 | 43.44 | 8.68800 | 2.5000000 | 0.75 | Electronics_West | P0 | 5 | true | 2 | 157 | 3.116667 | 4169.72 | 120 | 43.44 | 3.794140 |
| 3 | 8k0B7XX19Ykf | 2023-03-22 | nUX640AaXg | Home | P0443 | 3 | 17.74 | 0.05 | West | Online | 8 | 50.56 | 16.85333 | 0.3750000 | 0.15 | Home_West | P0 | 5 | true | 1 | 121 | 3.116667 | 4169.72 | 120 | 50.56 | 3.942746 |
| 4 | l8ahQz5YNOKz | 2023-01-02 | sBZyUSJLEP | Home | P0035 | 6 | 28.30 | 0.22 | North | Offline | 8 | 132.44 | 22.07333 | 0.7500000 | 1.32 | Home_North | P0 | 5 | true | 3 | 4 | 2.992908 | 4864.94 | 141 | 132.44 | 4.893652 |
| 5 | kmufgw8wx5qk | 2023-06-05 | GMfVH2ZWNX | Groceries | P0375 | 3 | 11.91 | 0.13 | North | Offline | 7 | 31.09 | 10.36333 | 0.4285714 | 0.39 | Groceries_North | P0 | 5 | true | 2 | 246 | 2.992908 | 4864.94 | 141 | 31.09 | 3.468545 |
2.2 Jawaban:
Apa itu Log Transform dan log1p?
Log Transform adalah teknik transformasi data yang menggunakan fungsi logaritma untuk mengubah distribusi data yang miring (skewed) menjadi lebih mendekati distribusi normal. Teknik ini umum dipakai dalam data science untuk menangani data yang memiliki rentang nilai sangat lebar.
log1p(x) = ln(1 + x)
Fungsi ini menambahkan 1 ke nilai x terlebih dahulu sebelum menghitung logaritmanya.
Bedanya dengan log() biasa:
| Fungsi | Rumus | Masalah |
|---|---|---|
| log(x) | ln(x) | log(0) = -Inf |
| log1p(x) | ln(1+x) | log1p(0) = 0 ✓ |
Kenapa Pakai log1p dan Bukan log Biasa?
log1p lebih aman dari log biasa karena bisa menangani nilai
0 tanpa menghasilkan error -Inf. Selain itu,
log1p juga lebih akurat secara numerik untuk nilai x yang
sangat kecil (mendekati 0), karena log(1+x) biasa rentan
kehilangan presisi akibat pembulatan floating point. Itulah mengapa
log1p sering digunakan dalam transformasi data, terutama
pada data bisnis seperti jumlah transaksi atau kuantitas barang yang
bisa bernilai 0.
Mengapa ada Safe_Total_Price?
Safe_Total_Price = ifelse(Total_Price <= 0, min_positive, Total_Price)
Karena log tidak bisa menghitung nilai negatif atau nol (hasilnya NaN/error), maka:
-
Jika
Total_Price <= 0→ diganti denganmin_positive(nilai positif terkecil di dataset) -
Jika
Total_Price > 0→ tetap pakai nilai aslinya
Baru setelah aman, dilakukan log transform: Log_Total_Price =
log1p(Safe_Total_Price)
Mengapa perlu Log Transform?
-
Data harga (
Total_Price) biasanya memiliki distribusi right-skewed (ada nilai yang sangat besar/outlier) - Setelah log transform, distribusi menjadi lebih normal
- Model statistik dan machine learning bekerja lebih baik pada data yang terdistribusi normal
Log Transform digunakan untuk menormalkan distribusi data yang skewed.
log1p() dipilih karena aman untuk nilai 0, dan
Safe_Total_Price dibuat terlebih dahulu untuk menghindari
error pada nilai negatif atau nol sebelum transformasi dilakukan. Log1p
juga lebih akurat secara numerik untuk nilai x yang sangat kecil
mendekati 0, tidak hanya sekadar “aman dari error”.
3 Robust Scaling
Pertanyaan: Jelaskan tentang teknik Robust Scaling.
3.1 Kode & Output
# Robust Scaling
data_robust <- data_bisnis %>%
mutate(
Quantity_Robust = (Quantity - median(Quantity)) / IQR(Quantity),
Unit_Price_Robust = (Unit_Price - median(Unit_Price)) / IQR(Unit_Price)
)
# Tampilkan 5 baris pertama
kable(head(data_robust, 5))| X | Transaction_ID | Transaction_Date | Customer_ID | Product_Category | Product_ID | Quantity | Unit_Price | Discount | Region | Sales_Channel | Delivery_Time | Total_Price | Price_per_Unit | Efficiency | Feature_Interaction | Cross_Term | ID_Prefix | ID_Length | ID_HasPattern | Discount_Level | Sales_Rank | Avg_Quantity_Region | Sum_Sales_Region | Count_Product_Region | Quantity_Robust | Unit_Price_Robust |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 7zmPHxF7XfN9 | 2021-07-14 | BAl3Y7yxev | Clothing | P0370 | 2 | 15.18 | 0.00 | North | Online | 5 | 30.36 | 15.18000 | 0.4000000 | 0.00 | Clothing_North | P0 | 5 | true | 1 | 253 | 2.992908 | 4864.94 | 141 | -0.5 | 0.2375237 |
| 2 | y4bCY9pKTBWU | 2020-11-16 | TYY0h5C190 | Electronics | P0185 | 5 | 10.22 | 0.15 | West | Offline | 2 | 43.44 | 8.68800 | 2.5000000 | 0.75 | Electronics_West | P0 | 5 | true | 2 | 157 | 3.116667 | 4169.72 | 120 | 1.0 | -0.3891346 |
| 3 | 8k0B7XX19Ykf | 2023-03-22 | nUX640AaXg | Home | P0443 | 3 | 17.74 | 0.05 | West | Online | 8 | 50.56 | 16.85333 | 0.3750000 | 0.15 | Home_West | P0 | 5 | true | 1 | 121 | 3.116667 | 4169.72 | 120 | 0.0 | 0.5609602 |
| 4 | l8ahQz5YNOKz | 2023-01-02 | sBZyUSJLEP | Home | P0035 | 6 | 28.30 | 0.22 | North | Offline | 8 | 132.44 | 22.07333 | 0.7500000 | 1.32 | Home_North | P0 | 5 | true | 3 | 4 | 2.992908 | 4864.94 | 141 | 1.5 | 1.8951358 |
| 5 | kmufgw8wx5qk | 2023-06-05 | GMfVH2ZWNX | Groceries | P0375 | 3 | 11.91 | 0.13 | North | Offline | 7 | 31.09 | 10.36333 | 0.4285714 | 0.39 | Groceries_North | P0 | 5 | true | 2 | 246 | 2.992908 | 4864.94 | 141 | 0.0 | -0.1756159 |
# Tabel Ringkasan Robust Scaling
kesimpulan <- data.frame(
Metrik = c("Median Before", "Median After", "IQR Before", "IQR After",
"Min Value", "Max Value", "Method Used"),
Quantity = c(
round(median(data_bisnis$Quantity), 2),
round(median(data_robust$Quantity_Robust), 2),
round(IQR(data_bisnis$Quantity), 2),
round(IQR(data_robust$Quantity_Robust), 2),
round(min(data_robust$Quantity_Robust), 2),
round(max(data_robust$Quantity_Robust), 2),
"(X - Median) / IQR"
),
Unit_Price = c(
round(median(data_bisnis$Unit_Price), 2),
round(median(data_robust$Unit_Price_Robust), 2),
round(IQR(data_bisnis$Unit_Price), 2),
round(IQR(data_robust$Unit_Price_Robust), 2),
round(min(data_robust$Unit_Price_Robust), 2),
round(max(data_robust$Unit_Price_Robust), 2),
"(X - Median) / IQR"
)
)
kable(kesimpulan, caption = "**Kesimpulan Robust Scaling**", align = 'c')| Metrik | Quantity | Unit_Price |
|---|---|---|
| Median Before | 3 | 13.3 |
| Median After | 0 | 0 |
| IQR Before | 2 | 7.91 |
| IQR After | 1 | 1 |
| Min Value | -1.5 | -1.84 |
| Max Value | 3 | 2.21 |
| Method Used | (X - Median) / IQR | (X - Median) / IQR |
3.2 Jawaban:
Apa itu Robust Scaling?
Robust Scaling menggunakan median dan IQR (Interquartile Range) sebagai dasar perhitungannya, karena kedua ukuran tersebut tidak sensitif terhadap outlier. Nilai mean misalnya, akan langsung bergeser jika terdapat satu nilai ekstrem dalam data. Sementara median tetap stabil karena hanya mempertimbangkan posisi tengah data, bukan besaran nilainya.
\[\text{Robust_Scaled} = \frac{x - \text{median}}{\text{IQR}}\]
Penjelasan Kode Per Baris
-
data_robust <- data_bisnis %>%— Membuat dataframe baru bernamadata_robustyang bersumber daridata_bisnis, kemudian diteruskan ke fungsi berikutnya menggunakan pipe%>%. -
mutate(— Digunakan untuk menambahkan kolom-kolom baru ke dalam dataframe. -
Quantity_Robust = (Quantity - median(Quantity)) / IQR(Quantity)— Membuat kolom baru dengan cara mengurangi setiap nilai Quantity dengan nilai mediannya, lalu dibagi IQR-nya sehingga menghasilkan nilai yang terskalakan dan tahan terhadap outlier. -
Unit_Price_Robust = (Unit_Price - median(Unit_Price)) / IQR(Unit_Price)— Melakukan proses yang sama pada kolom Unit_Price. -
kable(head(data_robust, 5))— Menampilkan 5 baris pertama dari dataframedata_robustdalam format tabel yang rapi.
Interpretasi Hasil
Berdasarkan hasil analisis, kedua variabel yaitu Quantity dan Unit_Price berhasil ditransformasi menggunakan Robust Scaling. Setelah transformasi, nilai median menjadi 0 dan IQR menjadi 1 pada kedua variabel.
Keunggulan utama Robust Scaling terletak pada ketahanannya terhadap outlier. Hal ini karena metode ini menggunakan median dan IQR yang tidak mudah terpengaruh oleh nilai ekstrem, berbeda dengan mean dan standar deviasi yang digunakan pada metode lain.
Robust Scaling adalah metode normalisasi yang menggunakan median dan IQR sehingga tahan terhadap outlier. Data yang telah di-scaling menjadi lebih stabil dan siap digunakan untuk analisis lanjutan seperti regresi, klasifikasi, maupun model machine learning yang membutuhkan skala data seragam.
Referensi
-
Wickham, H., Çetinkaya-Rundel, M., & Grolemund, G.
(2023). R for Data Science (2nd ed.). O’Reilly Media.
[Akses Edisi Ke-2 Online] -
Siregar, B. (n.d.). Data Science Programming.
Bookdown.
[Akses Online]