Market Basket Analysis (MBA) adalah teknik analisa yang digunakan oleh bisnis di bidang ritel untuk mencari asosiasi produk yang kuat, atau dengan kata lain menemukan paket produk yang bisa berdampak besar pada penjualan. Algoritma yang bisa digunakan di R untuk melakukan MBA ini adalah apriori dari package arules. Data yang diperlukan hanya dua, yaitu data transaksi dan data produk. Dengan paket produk yang ditemukan, bisnis dapat melakukan beberapa hal berikut: • Membuat paket produk dengan penawaran menarik. • Menyusun produk dengan asosiasi kuat secara berdampingan pada rak toko. • Menyusun tampilan katalog website e-commerce. • Memberikan rekomendasi produk.
read.transactions(file = "https://academy.dqlab.id/dataset/data_transaksi.txt", format = "single", sep = "\t", cols = c(1,2), skip=1)
## transactions in sparse format with
## 10 transactions (rows) and
## 4 items (columns)
Keterangan code: • File : Parameter lokasi file yang bisa berasal dari url di web satau lokal. Pada contoh ini dibaca file data_transaksi.txt yang berlokasi di website academy.dqlab.id. • https://academy.dqlab.id/dataset/data_transaksi.txt: lokasi dataset yang terdapat di web DQLab. Jika lokasi file dan aplikasi R terdapat di komputer lokal Anda, maka gantilah dengan lokasi file di lokal. Misalkan c:_transaksi.txt • format: Format bisa “single” atau “basket”. o “single” artinya tiap item transaksi dituliskan terpisah baris demi baris, dan ini cocok dengan format dari file kita. o “basket” artinya seluruh item per transaksi ditulis per baris. • sep: separator character atau karakter pemisah antar kolom, untuk file ini karakter pemisahnya adalah tab atau dalam notasi di R ditulis dengan ". • cols: indeks dari kolom-kolom yang digunakan. Untuk format single maka kolom harus dua saja, kolom pertama adalah kode transaksi sedangkan kolom kedua menunjukkan item transaksi. Penulisan c(1,2) pada contoh kita artinya kolom pertama dan kedua yang kita gunakan. • skip: jumlah baris yang dilewati sebelum mulai membaca data. Untuk dataset kita, baris pertama adalah header dan tidak diperlukan, jadi kita masukkan 1 sebagai input.
Keterangan hasil: • transactions in sparse format: Ini artinya transaksi dalam bentuk sparse (tersebar). Ini mungkin akan lebih jelas ketika divisualiasikan dalam bentuk matrix, ini akan kita praktekkan pada beberapa subbab di depan. • 10 transactions (rows): dataset kita secara total memiliki 10 transaksi. Ada informasi rows atau baris disini, ini bukan berarti data kita ada 10 baris di file kita. Karena pada kenyataannya, file memiliki 23 baris data. • 4 items (kolom): dataset kita secara total memiliki 4 item unik.
#Menampilkan Daftar Item Transaksi Item-item yang terdapat pada objek transactions dapat dilihat pada komponen itemInfo dengan didahului aksesor @, jadi ditulis @iteminfo. Ini bermanfaat untuk melihat daftar unik item yang terdapat pada data transaksi yang sedang kita analisa.
transaksi <- read.transactions(file = "https://academy.dqlab.id/dataset/data_transaksi.txt", format = "single", sep = "\t", cols = c(1,2), skip=1)
transaksi@itemInfo
## labels
## 1 Gula
## 2 Pet Food
## 3 Sirup
## 4 Teh Celup
Terlihat ada empat item yang terdapat di seluruh data transaksi kita, yaitu Gula, Pet Food, Sirup dan Teh Celup
#Menampilkan Daftar Kode Transaksi Sepuluh transaksi yang telah dibaca oleh read.transactions dapat dilihat detil kode-kodenya dengan menggunakan komponen itemsetInfo dengan aksesor @, atau lengkapnya ditulis dengan @itemsetInfo. Daftar ini bisa bermanfaat sebagai basis untuk menganalisa atau melakukan validasi dengan data yang ada pada sistem ritel.
transaksi@itemsetInfo
## transactionID
## 1 #01
## 2 #02
## 3 #03
## 4 #04
## 5 #05
## 6 #06
## 7 #07
## 8 #08
## 9 #09
## 10 #10
Ada kalanya kita ingin melihat sebaran item pada keseluruhan transaksi kita. Dengan menggunakan daftar output berupa teks akan terasa sangat panjang. Sebagai salah satu solusinya, kita bisa menampilkan sebaran ini dalam bentuk matrix dua dimensi, dimana baris matrix urutan item dan pada kolom adalah item transaksi. Untuk lebih jelasnya, mari kita langsung praktekkan saja. Matrix dari objek transaction dapat dilihat dari komponen data menggunakan aksesor @, ditulis lengkap sebagai @data.
transaksi@data
## 4 x 10 sparse Matrix of class "ngCMatrix"
##
## [1,] . | . . | . . . | |
## [2,] | . | . . | | . . |
## [3,] | . | | | . | . . |
## [4,] | | . | | | | | | .
Berikut adalah penjelasan hasilnya: • 4 x 10 : artinya terdapat 4 item dan 10 transaksi. • [1,] s/d [4,] : artinya index yang mewakili tiap item dalam transaksi. • Simbol tanda titik . menunjukkan item tidak ada di transaksi. • Simbol garis lurus | menunjukkan bahwa item ada di transaksi.
Item Frequency adalah jumlah kemunculan sebuah item dalam transaksi.Untuk menghasilkan informasi ini kita gunakan fungsi itemFrequency dengan input objek transaction, dan hasilnya berupa named vector atau vector yang bisa diakses dengan nama.
itemFrequency(transaksi, type="absolute")
## Gula Pet Food Sirup Teh Celup
## 4 5 6 8
Ini artinya Gula memiliki kemunculan 4 kali dari seluruh transaksi yang ada, Pet Food muncul sebanyak 5 kali, Sirup sebanyak 6 kali, dan Teh Celup sebanyak 8 kali. Fungsi itemFrequency ini sangat penting untuk membantu kita menganalisa transaksi yang lebih kompleks dimana item yang terlibat lebih banyak dan transaksi yang terjadi lebih besar dari contoh kita saat ini. Klik tombol Submit Code untuk melanjutkan ke bagian berikutnya # Grafik Item Frequency
itemFrequencyPlot(transaksi)
# Statistik Top 3 Statistik sederhana untuk menjawab pertanyaaan seperti “Mana 3 item yang memiliki jumlah terbanyak di seluruh transaksi?” tidak bisa langsung dilakukan dengan satu fungsi di R, tapi perlu penggabungan beberapa perintah dimana salah satunya adalah fungsi sort. Mari kita mulai praktekkan, dimulai dari menjalankan code yang telah ada pada code editor. Code ini berfungsi untuk menampilkan data_item yang merupakan variable yang nilainya merupakan hasil pemanggilan fungsi itemFrequency.
data_item <- itemFrequency(transaksi, type="absolute")
data_item <- sort(data_item, decreasing = TRUE)
data_item[1:3]
## Teh Celup Sirup Pet Food
## 8 6 5
Dari tampilan ini terlihat kita sudah berhasil mengambil tiga item dengan jumlah terbanyak. Tahap terakhir adalah merubah hasil yang berupa vector ini ke dalam data frame.
data_item <- data.frame("Nama Produk" = names(data_item), "Jumlah" = data_item, row.names = NULL)
str(data_item)
## 'data.frame': 4 obs. of 2 variables:
## $ Nama.Produk: chr "Teh Celup" "Sirup" "Pet Food" "Gula"
## $ Jumlah : int 8 6 5 4
Saatnya kita menghasilkan rule dari transaksi kita. Seperti diketahui, rule adalah formula yang menyatakan kombinasi dari dua itemset. Satu itemset ada di bagian kiri rule (left hand side) dan satunya di bagian kanan (right hand side). Untuk menghasilkan rule ini, kita gunakan fungsi apriori
apriori(transaksi)
## Apriori
##
## Parameter specification:
## confidence minval smax arem aval originalSupport maxtime support minlen
## 0.8 0.1 1 none FALSE TRUE 5 0.1 1
## maxlen target ext
## 10 rules TRUE
##
## Algorithmic control:
## filter tree heap memopt load sort verbose
## 0.1 TRUE TRUE FALSE TRUE 2 TRUE
##
## Absolute minimum support count: 1
##
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[4 item(s), 10 transaction(s)] done [0.00s].
## sorting and recoding items ... [4 item(s)] done [0.00s].
## creating transaction tree ... done [0.00s].
## checking subsets of size 1 2 3 done [0.00s].
## writing ... [3 rule(s)] done [0.00s].
## creating S4 object ... done [0.00s].
## set of 3 rules
perhatikan baris terakhir dimana tertulis “set of 3 rules”. Ini artinya dengan fungsi apriori ini, kita mendapatkan tiga rules. Kita akan ulas lebih jauh mengenai tiga rules ini pada praktek berikutnya.
mba <- apriori(transaksi)
## Apriori
##
## Parameter specification:
## confidence minval smax arem aval originalSupport maxtime support minlen
## 0.8 0.1 1 none FALSE TRUE 5 0.1 1
## maxlen target ext
## 10 rules TRUE
##
## Algorithmic control:
## filter tree heap memopt load sort verbose
## 0.1 TRUE TRUE FALSE TRUE 2 TRUE
##
## Absolute minimum support count: 1
##
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[4 item(s), 10 transaction(s)] done [0.00s].
## sorting and recoding items ... [4 item(s)] done [0.00s].
## creating transaction tree ... done [0.00s].
## checking subsets of size 1 2 3 done [0.00s].
## writing ... [3 rule(s)] done [0.00s].
## creating S4 object ... done [0.00s].
inspect(mba)
## lhs rhs support confidence coverage lift count
## [1] {} => {Teh Celup} 0.8 0.8 1.0 1.000000 8
## [2] {Pet Food} => {Sirup} 0.4 0.8 0.5 1.333333 4
## [3] {Gula,Pet Food} => {Sirup} 0.1 1.0 0.1 1.666667 1
Terlihat kalau variable mba menyimpan tiga rules dengan kolom-kolom berikut: • lhs: itemset di bagian kiri (left hand side) • rhs: itemset di bagian kanan (right hand side) • support, confidence dan lift: metrik-metrik yang digunakan untuk menilai kualitas dari rule. Umumnya semakin besar semakin baik. Detil dari metrik-metrik ini akan dibahas pada bab berikutnya. Kalau fokus kita kembali ke itemset lhs dan rhs untuk product packaging, terlihat rule kedua yaitu {Pet Food} => {Sirup} cukup menarik, karena support 0.4 menunjukkan bahwa kombinasi ini terdapat di 40 persen poulasi - berarti 4 dari 10 transaksi untuk dataset kita. Nilai lift juga di atas 1, yang artinya rule ini memiliki asosiasi tinggi antar itemset yang terdapat di rule ini. Sedangkan {} => {Teh Celup} tidak menarik karena hanya berisi satu item. Rule sisanya, {Gula, Peta Food} = > {Sirup} terlalu unik - ini ditunjukkan dengan support 0.1 (10%) yang artinya hanya terdapat di 1 dari 10 transaksi. Apa makna dari rule jika ingin kita aplikasikan? Artinya ada beberapa opsi action item yang bisa kita lakukan: • rekomendasikan kepada setiap pelanggan yang membeli Pet Food untuk membeli Sirup. • rak display Pet Food dan Sirup bisa didekatkan. • Pet Food dan Sirup dipaketkan bersama dan dijual dengan harga khusus.
Dari hasil inspect objek mba yang bertipe association rules di praktek sebelumnya, kita sekarang mengerti bahwa objek tersebut mengandung banyak informasi termasuk itemset yang terdapat di left hand side dan right hand side. Ini penting untuk bisnis, misalkan untuk inventory. Kita ingin menjawab, adakah item yang kurang laku sebelumnya ada di dalam itemset dari rules yang dihasilkan oleh apriori? Jika ada, mungkin saya bisa paketkan bersama sehingga kemungkinan besar terjual lebih banyak. Untuk melakukan ini kita akan melakukan filter atau subsetting dari rules. Banyak cara, salah satunya adalah dengan menggunakan gabungan function inspect, subset dan operator %in% dengan format berikut.
inspect(subset(mba, rhs %in% "Sirup"))
## lhs rhs support confidence coverage lift count
## [1] {Pet Food} => {Sirup} 0.4 0.8 0.5 1.333333 4
## [2] {Gula,Pet Food} => {Sirup} 0.1 1.0 0.1 1.666667 1
Filter dari praktek sebelumnya hanya berfokus kepada rhs, tentunya bisa juga dengan lhs. Berikut adalah contoh perintah inspect untuk filter lhs dengan item Gula.
inspect(subset(mba, lhs %in% "Gula"))
## lhs rhs support confidence coverage lift count
## [1] {Gula,Pet Food} => {Sirup} 0.1 1 0.1 1.666667 1
Kedua praktek sebelumnya menerapkan filter pada lhs atau rhs pada suatu waktu. Kita sebenarnya bisa melakukan filter untuk kedua sisi dengan menggunakan operator & untuk AND dan operator | untuk OR. Berikut adalah contoh perintah inspect untuk filter lhs dengan item Pet Food dan rhs dengan item Sirup.
inspect(subset(mba,lhs%in%"Pet Food" & rhs %in%"Sirup"))
## lhs rhs support confidence coverage lift count
## [1] {Pet Food} => {Sirup} 0.4 0.8 0.5 1.333333 4
## [2] {Gula,Pet Food} => {Sirup} 0.1 1.0 0.1 1.666667 1
Sebeumnya kita telah
menghasilkan tiga rules dengan function apriori secara default tanpa parameter apapun. Padahal sebenarnya kita bisa memasukkan parameter tambahan berupa support dan confidence. Tanpa parameter tambahan tersebut, maka nilai minimum support adalah 0.1 dan minimum confidence adalah 0.8 sebagai filter dari function apriori. Berikut adalah perintah untuk menghasilkan kembali association rules dengan function apriori, tapi kali ini dengan tambahan parameter minimum support dan confidence masing-masing bernilai 0.1 dan 0.5.
apriori(transaksi, parameter = list(supp = 0.1, confidence = 0.5))
## Apriori
##
## Parameter specification:
## confidence minval smax arem aval originalSupport maxtime support minlen
## 0.5 0.1 1 none FALSE TRUE 5 0.1 1
## maxlen target ext
## 10 rules TRUE
##
## Algorithmic control:
## filter tree heap memopt load sort verbose
## 0.1 TRUE TRUE FALSE TRUE 2 TRUE
##
## Absolute minimum support count: 1
##
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[4 item(s), 10 transaction(s)] done [0.00s].
## sorting and recoding items ... [4 item(s)] done [0.00s].
## creating transaction tree ... done [0.00s].
## checking subsets of size 1 2 3 done [0.00s].
## writing ... [16 rule(s)] done [0.00s].
## creating S4 object ... done [0.00s].
## set of 16 rules
Perhatikan pada akhir baris output, terdapat 16 rule. Lebih banyak dibandingkan eksekusi perintah apriori sebelumnya yang hanya menghasilkan 3 rule
mba <- apriori(transaksi, parameter = list(supp = 0.1, confidence = 0.5))
## Apriori
##
## Parameter specification:
## confidence minval smax arem aval originalSupport maxtime support minlen
## 0.5 0.1 1 none FALSE TRUE 5 0.1 1
## maxlen target ext
## 10 rules TRUE
##
## Algorithmic control:
## filter tree heap memopt load sort verbose
## 0.1 TRUE TRUE FALSE TRUE 2 TRUE
##
## Absolute minimum support count: 1
##
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[4 item(s), 10 transaction(s)] done [0.00s].
## sorting and recoding items ... [4 item(s)] done [0.00s].
## creating transaction tree ... done [0.00s].
## checking subsets of size 1 2 3 done [0.00s].
## writing ... [16 rule(s)] done [0.00s].
## creating S4 object ... done [0.00s].
inspect(mba)
## lhs rhs support confidence coverage lift
## [1] {} => {Pet Food} 0.5 0.5000000 1.0 1.0000000
## [2] {} => {Sirup} 0.6 0.6000000 1.0 1.0000000
## [3] {} => {Teh Celup} 0.8 0.8000000 1.0 1.0000000
## [4] {Gula} => {Sirup} 0.2 0.5000000 0.4 0.8333333
## [5] {Gula} => {Teh Celup} 0.3 0.7500000 0.4 0.9375000
## [6] {Pet Food} => {Sirup} 0.4 0.8000000 0.5 1.3333333
## [7] {Sirup} => {Pet Food} 0.4 0.6666667 0.6 1.3333333
## [8] {Pet Food} => {Teh Celup} 0.3 0.6000000 0.5 0.7500000
## [9] {Sirup} => {Teh Celup} 0.4 0.6666667 0.6 0.8333333
## [10] {Teh Celup} => {Sirup} 0.4 0.5000000 0.8 0.8333333
## [11] {Gula,Pet Food} => {Sirup} 0.1 1.0000000 0.1 1.6666667
## [12] {Gula,Sirup} => {Pet Food} 0.1 0.5000000 0.2 1.0000000
## [13] {Gula,Sirup} => {Teh Celup} 0.1 0.5000000 0.2 0.6250000
## [14] {Pet Food,Sirup} => {Teh Celup} 0.2 0.5000000 0.4 0.6250000
## [15] {Pet Food,Teh Celup} => {Sirup} 0.2 0.6666667 0.3 1.1111111
## [16] {Sirup,Teh Celup} => {Pet Food} 0.2 0.5000000 0.4 1.0000000
## count
## [1] 5
## [2] 6
## [3] 8
## [4] 2
## [5] 3
## [6] 4
## [7] 4
## [8] 3
## [9] 4
## [10] 4
## [11] 1
## [12] 1
## [13] 1
## [14] 2
## [15] 2
## [16] 2
Dengan 16 rules yang dihasilkan, kita bisa memiliki lebih banyak pilihan untuk melakukan filter lhs dan rhs seperti yang telah ditunjukkan pada bab Itemset and Rules. Berikut adalah contoh untuk filter dimana lhs atau rhs keduanya memiliki item Teh Celup.
mba <- subset(mba, lhs %in% "Teh Celup" | rhs %in% "Teh Celup")
inspect(mba)
## lhs rhs support confidence coverage lift
## [1] {} => {Teh Celup} 0.8 0.8000000 1.0 1.0000000
## [2] {Gula} => {Teh Celup} 0.3 0.7500000 0.4 0.9375000
## [3] {Pet Food} => {Teh Celup} 0.3 0.6000000 0.5 0.7500000
## [4] {Sirup} => {Teh Celup} 0.4 0.6666667 0.6 0.8333333
## [5] {Teh Celup} => {Sirup} 0.4 0.5000000 0.8 0.8333333
## [6] {Gula,Sirup} => {Teh Celup} 0.1 0.5000000 0.2 0.6250000
## [7] {Pet Food,Sirup} => {Teh Celup} 0.2 0.5000000 0.4 0.6250000
## [8] {Pet Food,Teh Celup} => {Sirup} 0.2 0.6666667 0.3 1.1111111
## [9] {Sirup,Teh Celup} => {Pet Food} 0.2 0.5000000 0.4 1.0000000
## count
## [1] 8
## [2] 3
## [3] 3
## [4] 4
## [5] 4
## [6] 1
## [7] 2
## [8] 2
## [9] 2
Kita bisa melakukan filter terhadap metrik kualitas dari association rules: support, confidence dan lift dengan function subset. Function yang sama untuk melakukan filter terhadap lhs dan rhs. Bedanya adalah karena angka, maka untuk ketiga metrik tersebut kita gunakan operator perbandingan angka Sebagai contoh, untuk melakukan filter terhadap objek mba dengan kondisi berikut: • lhs atau rhs memiliki Teh Celup • lift di atas 1 maka perintahnya adalah sebagai berikut subset(mba, (lhs %in% “Teh Celup” | rhs %in% “Teh Celup”) & lift>1) Perhatikan untuk ekspresi lhs dan rhs ditutup dengan kurung sebelum digabungkan dengan kondisi lift.
mba <- subset(mba, (lhs %in% "Teh Celup" | rhs %in% "Teh Celup") & lift>1)
inspect(mba)
## lhs rhs support confidence coverage lift count
## [1] {Pet Food,Teh Celup} => {Sirup} 0.2 0.6666667 0.3 1.111111 2
Hanya terdapat 1 rule sebagai hasil filter dan paket produk ini cukup menjanjikan, dimana Teh Celup menjadi komponen dari itemset di lhs
Sejauh ini Anda telah menghasilkan rules dan mengerti bagaimana metrik kualitas dapat digunakan sebagai basis pemilihan rule. Namun ketika item semakin banyak, maka proses memilih berdasarkan angka-angka saja cukup merepotkan. Kadangkala visualisasi bisa sangat membantu analisa di proses ini. Jenis visualisasi cukup banyak, namun kita akan gunakan visualisasi bertipe graph yang terdapat pada package arulesViz – suatu package dengan visualisasi khusus untuk association rules.
mba <- apriori(transaksi,parameter = list(supp = 0.1, confidence = 0.5))
## Apriori
##
## Parameter specification:
## confidence minval smax arem aval originalSupport maxtime support minlen
## 0.5 0.1 1 none FALSE TRUE 5 0.1 1
## maxlen target ext
## 10 rules TRUE
##
## Algorithmic control:
## filter tree heap memopt load sort verbose
## 0.1 TRUE TRUE FALSE TRUE 2 TRUE
##
## Absolute minimum support count: 1
##
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[4 item(s), 10 transaction(s)] done [0.00s].
## sorting and recoding items ... [4 item(s)] done [0.00s].
## creating transaction tree ... done [0.00s].
## checking subsets of size 1 2 3 done [0.00s].
## writing ... [16 rule(s)] done [0.00s].
## creating S4 object ... done [0.00s].
plot(subset(mba, lift>1.1), method="graph")
Lingkaran disini adalah titik pertemuan (asosiasi) dari item-item yang ada, dimana terdapat tanda panah sebagai garis penghubungnya. Tiap Item disini berupa teks. Besarnya bulatan menunjukkan popularitas, dan intensitas warna menunjukkan lift. Terlihat disini Gula ke Sirup, dan Pet Food ke Sirup memiliki lift yang relatif tinggi tapi supportnya tidak terlalu besar.