Watermelon v.2.1 Applikasi Point Of Sales Toko Bahan Bangunan
Data transaksi penjualan sering kali tidak digunakan atau diolah lebih lanjut untuk melihat kondisi bisnis yang sedang berjalan dan juga untuk melakukan inovasi atau pengembangan kedepan.
Dengan data penjualan yang terbentuk dari applikasi Point Of Sales yang digunakan sehari - hari, kami mencoba menampilkan sebuah laporan dan melakukan proses pengolahan data untuk menghasilkan visualisasi penjualan dalam grafik.
Setup awal untuk mengeset format chunk pada markdown
options(scipen = 999)Load library yang diperlukan
library(lubridate, warn.conflicts = F)
library(ggplot2)
library(scales)
#variable `warn.conflict = F` digunakan untuk menghilangkan warning yang timbul jika terjadi conflict dengan `base` packageImpor data sumber yang berbentuk file .csv
#import data
# Penyesuaian proses input dengan menentukan variable - variable sbb :
# - sep =";" -- separator yang digunakan dalam file csv yang di load menggunakan titik koma (;)
# - na.string = "\\N" -- data yang berisi tulisan \N akan di anggap data NA
# - stringAsFactors = F -- tidak otomatis merubah type data chr menjadi faktor
# - dec = "," -- menentukan format notasi decimal nya adalah koma, default di R adalah titik (.)
sales <- read.csv("assets/retail_mj.csv",
sep = ";", na.strings = "\\N",
stringsAsFactors = F,
dec = ","
)
#cek nama kolom
names(sales)## [1] "ID_Jenis" "Tanggal" "Bulan" "Tahun" "ID_Jual"
## [6] "ID_Barang" "stockAwal" "Jumlah" "stockAkhir" "Harga"
## [11] "ID_Post" "dummistk" "Keterangan" "ID_Satuan" "Batch"
## [16] "CreatedTime" "tglUpdate" "dolokasi" "Bln" "Thn"
## [21] "NoUrut" "Nomor" "Deskripsi" "ID_Lokasi" "IDP"
## [26] "ID_Anggota" "Nama_Barang" "Harga_Beli" "Satuan" "Kategori"
## [31] "JenisBarang"
#cek struktur data sales
str(sales)## 'data.frame': 520804 obs. of 31 variables:
## $ ID_Jenis : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Tanggal : chr "2002-01-01 00:00:00" "2002-01-01 00:00:00" "2002-01-01 00:00:00" "2002-01-01 00:00:00" ...
## $ Bulan : int 1 1 1 2 3 1 2 1 1 1 ...
## $ Tahun : int 4 4 4 4 4 4 4 4 4 4 ...
## $ ID_Jual : int 103051 103084 103101 103101 103101 103121 103121 103124 103148 103165 ...
## $ ID_Barang : int 2254 4724 3176 5044 6365 1245 5162 7608 2397 5849 ...
## $ stockAwal : num 952 254 12 15 7 ...
## $ Jumlah : num 2 1 1 1 2 0.5 5 1 13 1 ...
## $ stockAkhir : num 950 253 11 14 5 ...
## $ Harga : num 1500 10000 6500 37500 50000 12000 200 3000 150 27500 ...
## $ ID_Post : num NA NA NA NA NA NA NA NA NA NA ...
## $ dummistk : num NA NA NA NA NA NA NA NA NA NA ...
## $ Keterangan : num 4166002022 4166002023 4166002024 4166002024 4166002024 ...
## $ ID_Satuan : int 3 91 3 91 13 2 45 3 3 3 ...
## $ Batch : chr "600" "7500" "5250" "30368" ...
## $ CreatedTime: chr "2016-08-03 08:17:43" "2016-08-03 09:21:41" "2016-08-03 10:17:53" "2016-08-03 10:18:08" ...
## $ tglUpdate : chr "2016-08-03 08:17:43" "2016-08-03 09:21:41" "2016-08-03 10:17:53" "2016-08-03 10:18:08" ...
## $ dolokasi : int NA NA NA NA NA NA NA NA NA NA ...
## $ Bln : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Thn : int 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 ...
## $ NoUrut : num 4166002022 4166002023 4166002024 4166002024 4166002024 ...
## $ Nomor : chr "Umum" "Umum" "Umum" "Umum" ...
## $ Deskripsi : chr "" "" "" "" ...
## $ ID_Lokasi : int 4 4 4 4 4 4 4 4 4 4 ...
## $ IDP : int NA NA NA NA NA NA NA NA NA NA ...
## $ ID_Anggota : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Nama_Barang: chr "IN BOW BIASA" "AVIAN 100CC" "EMBER BESAR HITAM" "REDDISH CLAY V-09" ...
## $ Harga_Beli : num 600 8302 5250 39000 37200 ...
## $ Satuan : chr "PCS" "KLG" "PCS" "KLG" ...
## $ Kategori : chr "ALAT LISTRIK" "BANGUNAN" "BANGUNAN" "BANGUNAN" ...
## $ JenisBarang: chr "INBOW" "CAT AVIAN" "EMBER" "POLITUR" ...
Tanggal : Tanggal transaksiBln : Bulan transaksiThn : Tahun transaksiNama_Barang : Deskripsi Barang yang di jualHarga : Harga JualJumlah : Jumlah barang yang di jualJenisBarang : Sub Kategori barangNoUrut : Nomor urut transaksi,Kategori : Kategori Barang#Subsetting Data hanya menampilkan 9 kolom seperti diatas
#Assign ke data frame baru
sales_new <- sales[,
c("Tanggal","Bln","Thn","Nama_Barang","Harga","Jumlah",
"JenisBarang","NoUrut","Kategori")
]
str(sales_new)## 'data.frame': 520804 obs. of 9 variables:
## $ Tanggal : chr "2002-01-01 00:00:00" "2002-01-01 00:00:00" "2002-01-01 00:00:00" "2002-01-01 00:00:00" ...
## $ Bln : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Thn : int 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 ...
## $ Nama_Barang: chr "IN BOW BIASA" "AVIAN 100CC" "EMBER BESAR HITAM" "REDDISH CLAY V-09" ...
## $ Harga : num 1500 10000 6500 37500 50000 12000 200 3000 150 27500 ...
## $ Jumlah : num 2 1 1 1 2 0.5 5 1 13 1 ...
## $ JenisBarang: chr "INBOW" "CAT AVIAN" "EMBER" "POLITUR" ...
## $ NoUrut : num 4166002022 4166002023 4166002024 4166002024 4166002024 ...
## $ Kategori : chr "ALAT LISTRIK" "BANGUNAN" "BANGUNAN" "BANGUNAN" ...
#Membuat data frame baru `sales_datafix` dengan mengeluarkan baris yang ada kolom berisi NA
sales_datafix <- sales_new[rowSums(is.na(sales_new))==0 & sales_new$Jumlah >0,]
#cek perubahan struktur data
str(sales_datafix)## 'data.frame': 499334 obs. of 9 variables:
## $ Tanggal : chr "2002-01-01 00:00:00" "2002-01-01 00:00:00" "2002-01-01 00:00:00" "2002-01-01 00:00:00" ...
## $ Bln : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Thn : int 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 ...
## $ Nama_Barang: chr "IN BOW BIASA" "AVIAN 100CC" "EMBER BESAR HITAM" "REDDISH CLAY V-09" ...
## $ Harga : num 1500 10000 6500 37500 50000 12000 200 3000 150 27500 ...
## $ Jumlah : num 2 1 1 1 2 0.5 5 1 13 1 ...
## $ JenisBarang: chr "INBOW" "CAT AVIAN" "EMBER" "POLITUR" ...
## $ NoUrut : num 4166002022 4166002023 4166002024 4166002024 4166002024 ...
## $ Kategori : chr "ALAT LISTRIK" "BANGUNAN" "BANGUNAN" "BANGUNAN" ...
#merubah kolom tanggal menjadi as.Date
sales_datafix$Tanggal <- as.Date(sales_datafix$Tanggal)#merubah kolom Nama_Barang,Satuan,NoUrut sekaligus menjadi `as.factor`
sales_datafix[,c("Nama_Barang","JenisBarang","NoUrut","Kategori")] <-
lapply(
sales_datafix[,c("Nama_Barang","JenisBarang","NoUrut","Kategori")],
FUN = as.factor
)#cek struktur data setelah di lakukan perubahan
str(sales_datafix)## 'data.frame': 499334 obs. of 9 variables:
## $ Tanggal : Date, format: "2002-01-01" "2002-01-01" ...
## $ Bln : int 1 1 1 1 1 1 1 1 1 1 ...
## $ Thn : int 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 ...
## $ Nama_Barang: Factor w/ 6073 levels "","10/20 BIRU KITA",..: 1894 484 1303 4410 4814 3746 4749 4156 2075 1908 ...
## $ Harga : num 1500 10000 6500 37500 50000 12000 200 3000 150 27500 ...
## $ Jumlah : num 2 1 1 1 2 0.5 5 1 13 1 ...
## $ JenisBarang: Factor w/ 584 levels "ADAPTOR","AIR ACCU",..: 181 86 128 421 480 352 474 415 193 184 ...
## $ NoUrut : Factor w/ 290416 levels "2150000000","4140000000",..: 66191 66192 66193 66193 66193 66194 66194 66195 66196 66197 ...
## $ Kategori : Factor w/ 12 levels "ALAT LISTRIK",..: 1 4 4 4 4 4 4 1 1 10 ...
#cek minimal dan maximal tanggal transaksi
min(sales_datafix$Tanggal)## [1] "2002-01-01"
max(sales_datafix$Tanggal)## [1] "2020-12-21"
#Berhubung kita hanya akan menampilkan data pada periode 2014 s/d 2020
#maka tahun dibawah 2014 kita hilangkan
sales_datafix <- sales_datafix[sales_datafix$Thn >= 2014,]
unique(sales_datafix$Thn)## [1] 2014 2015 2016 2017 2018 2019 2020
#menambahkan kolom TotalHarga yang berasal dari kolom `Harga` x `Jumlah`
sales_datafix$TotalHarga <- sales_datafix$Harga * sales_datafix$Jumlah#cek isi data untuk melihat bentuk data
head(sales_datafix)## Tanggal Bln Thn Nama_Barang Harga Jumlah JenisBarang NoUrut
## 112 2014-08-31 8 2014 AQUA 600 ML 38500 5 AIR MINERAL 4140000000
## 113 2014-08-31 8 2014 AQUA GALON 13000 6 AIR MINERAL 4140000000
## 115 2014-09-01 9 2014 SEMEN HOLSIN 50KG 68500 1 SEMEN 4140000004
## 116 2014-09-01 9 2014 SEMEN HOLSIN 50KG 68500 1 SEMEN 4140000005
## 117 2014-09-01 9 2014 SEMEN HOLSIN 40KG 55000 2 SEMEN 4140000006
## 121 2014-09-01 9 2014 AQUA GALON 14000 2 AIR MINERAL 4140000010
## Kategori TotalHarga
## 112 GAS & MINUMAN 192500
## 113 GAS & MINUMAN 78000
## 115 BANGUNAN 68500
## 116 BANGUNAN 68500
## 117 BANGUNAN 110000
## 121 GAS & MINUMAN 28000
Menambahan Kolom Periode yang berisi Tahun-Bulan transaksi
sales_datafix$Periode <- format(as.Date(sales_datafix$Tanggal),'%Y-%m')Aggregasi data Total Penjualan dalam setiap tahunnya
#load theme dari Algorima
theme_algoritma <- theme(legend.key = element_rect(fill="black"),
legend.background = element_rect(color="white", fill="#263238"),
plot.subtitle = element_text(size=6, color="white"),
panel.background = element_rect(fill="#dddddd"),
panel.border = element_rect(fill=NA),
panel.grid.minor.x = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.major.y = element_line(color="darkgrey", linetype=2),
panel.grid.minor.y = element_blank(),
plot.background = element_rect(fill="#263238"),
text = element_text(color="white"),
axis.text = element_text(color="white")
)#Aggregasi `sum` kolom `TotalHarga` terhadap Tahun
total_sales <- aggregate(cbind(Jumlah,TotalHarga) ~ Thn, data = sales_datafix, FUN = sum)
total_sales## Thn Jumlah TotalHarga
## 1 2014 44644.0 265310530
## 2 2015 717351.6 5375859263
## 3 2016 959318.3 9100774237
## 4 2017 609248.3 4769742808
## 5 2018 1489548.8 7769461858
## 6 2019 753941.2 5024420806
## 7 2020 549600.2 3886486010
Ploting menggunakan bar chart untuk melihat perbandingan Total penjualan dari tahun ke tahun
ggplot(data = total_sales, aes(x = Thn, y = TotalHarga, fill="skyblue4"))+
geom_col()+
geom_text(aes(
label = formatC(round(TotalHarga,0),big.mark = ",", digits = 12),
y = TotalHarga +(TotalHarga*0.075)
), size = 3)+
labs(
x = "Tahun",
y = "Total Penjualan",
title = "Total Pendapatan Penjualan",
subtitle = paste("Periode ",min(total_sales$Thn),"-", max(total_sales$Thn)),
caption = "source :Data dari Applikasi Penjualan di cv. Mekar Jaya Maniis Purwakarta"
)+
scale_y_continuous(labels = comma_format(big.mark = ","))+
scale_x_continuous(breaks = breaks_extended(8))+
scale_color_brewer(palette = "Set1")+
theme_algoritma +
theme(
legend.position = "none",
plot.title = element_text(hjust=0.5),
plot.subtitle = element_text(hjust = 0.5,size = 8, color = "blue"),
plot.caption = element_text(size = 5,face = "italic")
)+
geom_line( size=0.8, colour ="blue")
Insight :
Dari grafik terlihat mudah dipahami pada tahun berapa penjualan mengalami hasil yang tertinggi dan yang terendah.
Penjualan dengan total pendapatan penjualan tertinggi terjadi pada tahun 2016 yang mana dalam setahun berhasil membukukan penjualan lebih dari 9 Milyar.
Tahun 2018 kembali mendapatkan kenaikan penjualan setelah sempat turun hampir 50% di tahun 2017.
Untuk mengetahui lebih dalam, kita mencoba menampilkan 3 kategori utama dari role bisnis Toko Bahan Bangunan:
#Subsetting data hanya 3 kategori penjualan
#masukan dalam data plot
ggplot(data = sales_datafix[sales_datafix$Kategori %in%
c("ALAT LISTRIK","BANGUNAN","ELEKTRONIK"), ],
aes(x=Tanggal,
y=TotalHarga)) +
scale_y_continuous(labels = comma_format(big.mark = ","))+
geom_line(aes(col= Kategori),show.legend = F)+
facet_wrap( ~ Kategori)+
labs(
x = "Periode",
y = "Total Penjualan ",
title = "Facet Plot Top 3 Kategori",
subtitle = "Kategori Alat Listrik, Bangunan dan Elektronik"
)+
theme_algoritma+
theme(
legend.position = "none",
plot.title = element_text(hjust=0.5),
plot.subtitle = element_text(hjust = 0.5,size = 8, color = "blue"),
plot.caption = element_text(size = 5,face = "italic")
)Semen sebagai bahan baku utama yang digunakan dalam pembuatan bangunan, pastinya akan menjadi barang yang banyak dicari disetiap Toko Bahan Bangunan.
Mari kita lihat apakah data menunjukan semen sebagai barang yang menjadi penyumbang pendapatan tertinggi?
#melakukan aggregasi data untuk mendapatkan `Total Harga` untuk kategori Bangunan
agg_semen <- aggregate(TotalHarga ~ JenisBarang,
data = sales_datafix[sales_datafix$Kategori=='BANGUNAN',],
FUN = sum)
#Assign ke `df` data 10 penjualan terbanyak
df <-head(agg_semen[order(agg_semen$TotalHarga, decreasing = T),],10)# Tampilka dalam plot
ggplot(data = df, aes(x= reorder(JenisBarang,TotalHarga), y=TotalHarga,fill=JenisBarang)) +
geom_col(show.legend = F)+
coord_flip()+
labs(
x ="Nama Barang",
y ="Jumlah Penjualan",
title = "Top 10 Total Penjualan Kategori Bangunan ",
subtitle = paste("Periode ",min(total_sales$Thn),"-", max(total_sales$Thn)),
caption = "source :Data dari Applikasi Penjualan di cv. Mekar Jaya Maniis Purwakarta"
)+
geom_text(mapping = aes(label =formatC(round(TotalHarga,0),big.mark = ",",digits = 12),
y = TotalHarga/2), size=3)+
scale_y_continuous(labels = comma_format(big.mark = ","))+
scale_x_discrete(label = wrap_format(30))+
geom_hline(yintercept = mean(df$TotalHarga), linetype = 5, col = "Red")+
theme_algoritma +
# scale_fill_gradient(low = "yellow", high = "red") +
theme(
legend.position = "none",
plot.title = element_text(hjust=0.5),
plot.subtitle = element_text(hjust = 0.5,size = 10, color = "blue"),
plot.caption = element_text(size = 5,face = "italic"),
axis.text.y = element_text(size = 7)
)
* Dari plot diatas bisa dengan mudah kita simpulkan bahwa semen menjadi pertama yang memperoleh Total Penjualan Terbanyak
SEMEN# Subseting data penjualan yang nama barangnya mengandung kata "SEMEN"
# menggunakan fungsi `grepl`
jml_sales_semen <- aggregate(cbind(Jumlah , TotalHarga) ~ Nama_Barang,
data = sales_datafix[grepl("SEMEN",sales_datafix$Nama_Barang) ,],
FUN = sum
)
jml_sales_semen <- jml_sales_semen[order(jml_sales_semen$Jumlah,decreasing = T),]
jml_sales_semen## Nama_Barang Jumlah TotalHarga
## 11 SEMEN MP 40KG 20405.00 858932380
## 6 SEMEN GERSIK 40 KG 18192.00 826604500
## 4 SEMEN GARUDA 40KG 15009.00 688937250
## 20 SEMEN TIGA RODA 40 KG 14903.00 663482750
## 18 SEMEN RAJAWALI 40KG 11113.00 452137500
## 8 SEMEN HOLSIN 40KG 8309.00 400732750
## 10 SEMEN KANTONG 8070.00 40218500
## 7 SEMEN GERSIK 50KG 1755.00 99633500
## 16 SEMEN PUTIH 1 KG 1541.75 6479650
## 5 SEMEN GARUDA 50KG 1103.00 63291250
## 19 SEMEN SCG 40KG 821.00 34339000
## 9 SEMEN HOLSIN 50KG 673.00 35072500
## 3 SEMEN CONCH 40KG 618.00 14726500
## 15 SEMEN PEREKAT ALC ADHESIVE 408.00 28094000
## 13 SEMEN PADANG 40KG 297.00 11220000
## 12 SEMEN MP 50KG 87.00 4524000
## 2 SEMEN BIMA 40KG 80.00 2974500
## 21 SEMEN TIGA RODA 50KG 75.00 4935500
## 22 SEMEN WARNA PRIMA GROUT 34.00 522500
## 17 SEMEN PUTIH 40 KG 32.00 2682500
## 14 SEMEN PADANG 50KG 27.00 1737000
## 1 SEMEN ACIN HEBEL 20.00 1300000
# Distribusi plot
ggplot(jml_sales_semen, aes(x = reorder(Nama_Barang,Jumlah),
y = Jumlah,
fill= Jumlah)) +
geom_col(show.legend = F)+
coord_flip()+
labs(
x ="Nama Barang",
y ="Jumlah Penjualan",
title = "Total Penjualan Semen",
subtitle = paste("Periode ",min(total_sales$Thn),"-", max(total_sales$Thn)),
caption = "source :Data dari Applikasi Penjualan di cv. Mekar Jaya Maniis Purwakarta"
)+
geom_text(mapping = aes(label =formatC(round(Jumlah,0),big.mark = ",",digits = 12),
y =Jumlah + 500), size=3)+
scale_y_continuous(labels = comma_format(big.mark = ","))+
scale_x_discrete(label = wrap_format(30))+
theme_algoritma +
scale_fill_gradient(low = "yellow", high = "red") +
theme(
legend.position = "none",
plot.title = element_text(hjust=0.5),
plot.subtitle = element_text(hjust = 0.5,size = 10, color = "blue"),
plot.caption = element_text(size = 5,face = "italic"),
axis.text.y = element_text(size = 7)
)
Dari plot diatas, Semen MP 40KG menjadi top barang yang terjual tertinggi dari berbagai jenis semen yang dijual ditoko bahan bangunan ini.
Banyaknya transaksi yang terjadi tidak serta merta akan menghasilkan total penjualan yang tinggi. Karena bisa terjadi banyak transaksi namun barang-barang yang terjual nilainya kecil dll.
Mari kita lihat dari grafik sebaran data dibawah ini.
#membuat aggregasi data
sales_agg1 <- aggregate(NoUrut ~ Periode,data = sales_datafix, FUN = length)
sales_agg2 <- aggregate(TotalHarga ~ Periode,data = sales_datafix,FUN = sum)
#menggabungkan 2 data aggregasi menggunakan `merge` function
sales_agg <-merge(sales_agg1,sales_agg2,all = T)ggplot(sales_agg, aes(x = NoUrut,
y = TotalHarga
))+
geom_jitter(aes(size=NoUrut),col= "red", alpha = 0.5)+
labs(
y = "Total Penjualan",
x = "Jumlah Transaksi",
title ="Hubungan antara Jumlah Transaksi dan Total Penjualan",
subtitle = paste("Periode ",min(sales_agg$Periode)," - ", max(sales_agg$Periode)),
caption = "source :Data dari Applikasi Penjualan di cv. Mekar Jaya Maniis Purwakarta",
size =" Jml Transaksi"
)+
geom_smooth(method = "loess", formula = 'y ~ x')+
scale_y_continuous(labels = comma_format(big.mark = ","))+
scale_x_continuous(labels = comma_format(big.mark = ","))+
theme_algoritma +
theme(
legend.position = "bottom",
plot.title = element_text(hjust=0.5),
plot.subtitle = element_text(hjust = 0.5,size = 10, color = "blue"),
plot.caption = element_text(size = 5,face = "italic"),
axis.text = element_text(size = 8)
)
Kesimpulan yang bisa diambil dari penampakan graik diatas :