# Muhammad Dzaki Naufal
# 5003241147
# Data Mining W2 Latihan Soal
##### Read Data #####
setwd("C:/Users/Dzaki Naufal/Downloads")
# Load package
library(readxl)
## Warning: package 'readxl' was built under R version 4.4.3
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
library(scales)
## Warning: package 'scales' was built under R version 4.4.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
# Nama/path file
data_file <- "data_kopi.xlsx"
# Cek nama sheet
excel_sheets(data_file)
## [1] "produk" "transaksi"
# Membaca masing-masing sheet
Produk <- read_excel(data_file, sheet = "produk")
transaksi <- read_excel(data_file, sheet = "transaksi")
#cek masing2 sheet
head(Produk)
## # A tibble: 6 × 4
## id_produk nama_produk harga diskon
## <chr> <chr> <chr> <chr>
## 1 P01 Kopi Susu Rp15.000 10%
## 2 P02 Americano Rp12.000 0%
## 3 P03 Matcha Latte Rp18.000 5%
## 4 P04 Cappuccino Rp17.000 15%
## 5 P05 Es Kopi Gula Aren Rp16.000 20%
## 6 P06 Chocolate Latte Rp19.000 0%
head(transaksi)
## # A tibble: 6 × 4
## id_trx tgl_trx id_produk qty
## <dbl> <chr> <chr> <dbl>
## 1 1 01/09/2026 P02 1
## 2 2 01/09/2026 P05 2
## 3 3 01/09/2026 P04 2
## 4 4 01/09/2026 P02 5
## 5 5 02/09/2026 P07 1
## 6 6 02/09/2026 P01 1
str(Produk)
## tibble [8 × 4] (S3: tbl_df/tbl/data.frame)
## $ id_produk : chr [1:8] "P01" "P02" "P03" "P04" ...
## $ nama_produk: chr [1:8] "Kopi Susu" "Americano" "Matcha Latte" "Cappuccino" ...
## $ harga : chr [1:8] "Rp15.000" "Rp12.000" "Rp18.000" "Rp17.000" ...
## $ diskon : chr [1:8] "10%" "0%" "5%" "15%" ...
str(transaksi)
## tibble [345 × 4] (S3: tbl_df/tbl/data.frame)
## $ id_trx : num [1:345] 1 2 3 4 5 6 7 8 9 10 ...
## $ tgl_trx : chr [1:345] "01/09/2026" "01/09/2026" "01/09/2026" "01/09/2026" ...
## $ id_produk: chr [1:345] "P02" "P05" "P04" "P02" ...
## $ qty : num [1:345] 1 2 2 5 1 1 5 5 2 5 ...
##### Soal 1 Gabungkan sheet jadi data terpadu ######
# Gabungkan data berdasarkan id_produk
df_gabungan_mentah <- transaksi %>%
left_join(Produk,by = "id_produk") %>%
select(
id_trx,
tgl_trx,
nama_produk,
harga,
diskon,
qty
)
head(df_gabungan_mentah)
## # A tibble: 6 × 6
## id_trx tgl_trx nama_produk harga diskon qty
## <dbl> <chr> <chr> <chr> <chr> <dbl>
## 1 1 01/09/2026 Americano Rp12.000 0% 1
## 2 2 01/09/2026 Es Kopi Gula Aren Rp16.000 20% 2
## 3 3 01/09/2026 Cappuccino Rp17.000 15% 2
## 4 4 01/09/2026 Americano Rp12.000 0% 5
## 5 5 02/09/2026 Vietnam Drip Rp14.000 10% 1
## 6 6 02/09/2026 Kopi Susu Rp15.000 10% 1
##### Soal 2 Beberapa kolom pada df_produk dan df_transaksi tersimpan sebagai teks
#salin data
Produk_clean <- Produk
transaksi_clean <- transaksi
# 1. Konversi harga dari teks ke angka murni
Produk_clean$harga_num <- as.numeric(
gsub("[^0-9]", "", Produk_clean$harga)
)
# Verifikasi hasil konversi harga
head(Produk_clean[, c("harga", "harga_num")], 10)
## # A tibble: 8 × 2
## harga harga_num
## <chr> <dbl>
## 1 Rp15.000 15000
## 2 Rp12.000 12000
## 3 Rp18.000 18000
## 4 Rp17.000 17000
## 5 Rp16.000 16000
## 6 Rp19.000 19000
## 7 Rp14.000 14000
## 8 Rp20.000 20000
class(Produk_clean$harga_num)
## [1] "numeric"
sum(is.na(Produk_clean$harga_num))
## [1] 0
# 2. Konversi diskon ke pecahan desimal (0 - 1)
Produk_clean$diskon_num <- as.numeric(
gsub("%", "", Produk_clean$diskon)
) / 100
# Verifikasi hasil konversi diskon
head(Produk_clean[, c("diskon", "diskon_num")], 10)
## # A tibble: 8 × 2
## diskon diskon_num
## <chr> <dbl>
## 1 10% 0.1
## 2 0% 0
## 3 5% 0.05
## 4 15% 0.15
## 5 20% 0.2
## 6 0% 0
## 7 10% 0.1
## 8 25% 0.25
range(Produk_clean$diskon_num, na.rm = TRUE)
## [1] 0.00 0.25
sum(is.na(Produk_clean$diskon_num))
## [1] 0
# 3. Konversi qty menjadi numerik
transaksi_clean$qty_num <- as.numeric(
transaksi_clean$qty
)
# Verifikasi hasil konversi qty
head(transaksi_clean[, c("qty", "qty_num")], 10)
## # A tibble: 10 × 2
## qty qty_num
## <dbl> <dbl>
## 1 1 1
## 2 2 2
## 3 2 2
## 4 5 5
## 5 1 1
## 6 1 1
## 7 5 5
## 8 5 5
## 9 2 2
## 10 5 5
class(transaksi_clean$qty_num)
## [1] "numeric"
sum(is.na(transaksi_clean$qty_num))
## [1] 0
# 4. Konversi tanggal transaksi menjadi Date valid
transaksi_clean$tgl_trx_valid <- as.Date(
transaksi_clean$tgl_trx,
format = "%d/%m/%Y"
)
# Verifikasi hasil konversi tanggal
head(
transaksi_clean[, c("tgl_trx", "tgl_trx_valid")],
10
)
## # A tibble: 10 × 2
## tgl_trx tgl_trx_valid
## <chr> <date>
## 1 01/09/2026 2026-09-01
## 2 01/09/2026 2026-09-01
## 3 01/09/2026 2026-09-01
## 4 01/09/2026 2026-09-01
## 5 02/09/2026 2026-09-02
## 6 02/09/2026 2026-09-02
## 7 03/09/2026 2026-09-03
## 8 03/09/2026 2026-09-03
## 9 04/09/2026 2026-09-04
## 10 04/09/2026 2026-09-04
# 5. Gabungkan data hasil cleaning
df_gabungan_clean <- transaksi_clean %>%
left_join(Produk_clean, by = "id_produk") %>%
select(
id_trx,
tgl_trx_valid,
nama_produk,
harga_num,
diskon_num,
qty_num
)
# Verifikasi akhir
head(df_gabungan_clean)
## # A tibble: 6 × 6
## id_trx tgl_trx_valid nama_produk harga_num diskon_num qty_num
## <dbl> <date> <chr> <dbl> <dbl> <dbl>
## 1 1 2026-09-01 Americano 12000 0 1
## 2 2 2026-09-01 Es Kopi Gula Aren 16000 0.2 2
## 3 3 2026-09-01 Cappuccino 17000 0.15 2
## 4 4 2026-09-01 Americano 12000 0 5
## 5 5 2026-09-02 Vietnam Drip 14000 0.1 1
## 6 6 2026-09-02 Kopi Susu 15000 0.1 1
str(df_gabungan_clean)
## tibble [345 × 6] (S3: tbl_df/tbl/data.frame)
## $ id_trx : num [1:345] 1 2 3 4 5 6 7 8 9 10 ...
## $ tgl_trx_valid: Date[1:345], format: "2026-09-01" "2026-09-01" ...
## $ nama_produk : chr [1:345] "Americano" "Es Kopi Gula Aren" "Cappuccino" "Americano" ...
## $ harga_num : num [1:345] 12000 16000 17000 12000 14000 15000 17000 15000 14000 20000 ...
## $ diskon_num : num [1:345] 0 0.2 0.15 0 0.1 0.1 0.15 0.1 0.1 0.25 ...
## $ qty_num : num [1:345] 1 2 2 5 1 1 5 5 2 5 ...
##### Soal 3 Buat kolom-kolom turunan untuk tabel integrasi #####
# 1. Hitung total nilai transaksi per baris
df_gabungan_clean$total_bayar <-
df_gabungan_clean$qty_num *
df_gabungan_clean$harga_num *
(1 - df_gabungan_clean$diskon_num)
# 2. Ekstraksi nama hari transaksi
df_gabungan_clean$hari_transaksi <- format(
df_gabungan_clean$tgl_trx_valid,
"%A"
)
# 3. Kategori Diskon menggunakan nested ifelse
df_gabungan_clean$kategori_diskon <- ifelse(
df_gabungan_clean$diskon_num < 0.30,
"Rendah",
ifelse(
df_gabungan_clean$diskon_num <= 0.60,
"Sedang",
"Tinggi"
)
)
# Cek hasil kolom turunan
head(
df_gabungan_clean[
,
c(
"id_trx",
"total_bayar",
"hari_transaksi",
"kategori_diskon"
)
],
10
)
## # A tibble: 10 × 4
## id_trx total_bayar hari_transaksi kategori_diskon
## <dbl> <dbl> <chr> <chr>
## 1 1 12000 Tuesday Rendah
## 2 2 25600 Tuesday Rendah
## 3 3 28900 Tuesday Rendah
## 4 4 60000 Tuesday Rendah
## 5 5 12600 Wednesday Rendah
## 6 6 13500 Wednesday Rendah
## 7 7 72250 Thursday Rendah
## 8 8 67500 Thursday Rendah
## 9 9 25200 Friday Rendah
## 10 10 75000 Friday Rendah
##### SOAL 4 VISUALISASI #####
# 1. Distribusi frekuensi kategori diskon
table(df_gabungan_clean$kategori_diskon)
##
## Rendah
## 345
# 2. Membuat periode transaksi per bulan
library(lubridate)
## Warning: package 'lubridate' was built under R version 4.4.3
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
df_gabungan_clean$periode_transaksi <- floor_date(
df_gabungan_clean$tgl_trx_valid,
unit = "month"
)
tren_bulanan <- aggregate(
total_bayar ~ periode_transaksi,
data = df_gabungan_clean,
FUN = sum,
na.rm = TRUE
)
tren_bulanan <- tren_bulanan[
order(tren_bulanan$periode_transaksi),
]
# Line Chart
ggplot(
tren_bulanan,
aes(x = periode_transaksi, y = total_bayar)
) +
geom_line(color = "steelblue", linewidth = 1) +
geom_point(color = "steelblue", size = 2) +
labs(
title = "Tren Total Bayar per Bulan",
x = "Bulan Transaksi",
y = "Total Bayar"
) +
theme_minimal()

# 3. Agregasi Total Bayar per Produk
transaksi_produk <- aggregate(
total_bayar ~ nama_produk,
data = df_gabungan_clean,
FUN = sum,
na.rm = TRUE
)
transaksi_produk <- transaksi_produk[
order(transaksi_produk$total_bayar, decreasing = TRUE),
]
top_10_produk <- head(transaksi_produk, 10)
ggplot(
top_10_produk,
aes(x = reorder(nama_produk, total_bayar), y = total_bayar)
) +
geom_col(fill = "#3498DB") +
coord_flip() +
labs(
title = "Top 10 Produk Berdasarkan Total Bayar",
x = "Nama Produk",
y = "Total Bayar"
) +
theme_minimal()

# 4. Visualisasi Total Bayar Berdasarkan Kategori Diskon
transaksi_diskon <- aggregate(
total_bayar ~ kategori_diskon,
data = df_gabungan_clean,
FUN = sum,
na.rm = TRUE
)
ggplot(
transaksi_diskon,
aes(
x = kategori_diskon,
y = total_bayar,
fill = kategori_diskon
)
) +
geom_col() +
labs(
title = "Total Bayar Berdasarkan Kategori Diskon",
x = "Kategori Diskon",
y = "Total Bayar"
) +
theme_minimal() +
theme(legend.position = "none")

# 5. Boxplot Total Bayar Berdasarkan Kategori Diskon
ggplot(
df_gabungan_clean,
aes(
x = kategori_diskon,
y = total_bayar
)
) +
geom_boxplot() +
labs(
title = "Distribusi Total Bayar Berdasarkan Kategori Diskon",
x = "Kategori Diskon",
y = "Total Bayar"
) +
theme_minimal()
