# Memuat paket yang diperlukan untuk koneksi database dan visualisasi

library(DBI)
library(odbc)
library(ggplot2)

Pendahuluan

Laporan ini menyajikan analisis dan visualisasi data penjualan dan profit dari dataset coffee chain yang diambil dari dataset file SQL pada dataset tugas yang telah diberikan. Proses ini mengintegrasikan SQL untuk pengambilan data dan R untuk pengolahan, visualisasi, serta pengujian statistik.

Tujuan dari analisis, visualisasi, serta pengujian ini adalah untuk mengidentifikasi pola dan hubungan dalam data, serta mengetahui faktor-faktor yang memengaruhi kinerja bisnis pada dataset coffee chain, sehingga dapat memberikan insight yang mendukung pengambilan keputusan yang lebih tepat.

Koneksi Database SQL ke Rstudio

Karena database yang digunakan berasal dari file SQL, maka perlu dilakukan koneksi terlebih dahulu agar data yang ada dalam dataset coffee chain dapat diakses dan diolah dengan Rstudio. Proses koneksi dilakukan dengan sintaks berikut.

con3 <- DBI::dbConnect(odbc::odbc(),
               Driver = "MySQL ODBC 8.0 ANSI Driver",
               Server = "127.0.0.1",
               Database = "coffee_chain",
               UID = "root",
               PWD = "admin123",
               Port = 3306)

Untuk lebih memahami struktur dataset yang digunakan, dapat dilakukan beberapa sintaks untuk menampilkan informasi terkait tabel yang tersedia serta atribut (kolom) yang terdapat pada masing-masing tabel dalam database.

# melihat tabel yg ada pada koneksi con3
dbListTables(con3)
# melihat nama atribut tabel
dbListFields(con3, "product")
dbListFields(con3, "location")
dbListFields(con3, "facttable")

Analisis, Visualisasi, dan Pengujian

Untuk memudahkan analisis serta pengujian dapat dibuat terlebih dulu tabel yang berisi beberapa variabel-variabel yang akan diuji karena tidak semua variabel akan digunakan untuk proses analisis dan pengujian.

testtable <- dbGetQuery(con3, "SELECT f.Profit, f.Sales, f.`Area Code`, f.ProductId, p.`Product Type`, l.`Market Size`
FROM facttable f
INNER JOIN product p USING (ProductId)
INNER JOIN location l USING (`Area code`);")
head(testtable)
##   Profit Sales Area Code ProductId Product Type  Market Size
## 1     94   219       719         1       Coffee Major Market
## 2     68   190       970         2       Coffee Major Market
## 3    101   234       970         3       Coffee Major Market
## 4     30   100       303        13          Tea Major Market
## 5     54   134       303         5     Espresso Major Market
## 6     53   180       720         6     Espresso Major Market

Kemudian, dapat diperiksa distribusi dari beberapa variabel termasuk ke dalam distribusi normal atau tidak untuk mengetahui uji yang tepat untuk variabel tersebut.

# H0 :Berdistribusi normal
# H1 :Tidak berdistribusi normal
testprofit <- shapiro.test(testtable$Profit)
print(testprofit)
## 
##  Shapiro-Wilk normality test
## 
## data:  testtable$Profit
## W = 0.79969, p-value < 2.2e-16
cat("Keputusan:",
    ifelse(testprofit$p.value < 0.05,
           "H0 ditolak, sehingga dapat diambil kesimpulan bahwa data profit tidak berdistribusi normal",
           "H0 gagal ditolak, sehingga dapat diambil kesimpulan bahwa data profit berdistribusi normal"), "\n")
## Keputusan: H0 ditolak, sehingga dapat diambil kesimpulan bahwa data profit tidak berdistribusi normal
testsales <- shapiro.test(testtable$Sales)
print(testsales)
## 
##  Shapiro-Wilk normality test
## 
## data:  testtable$Sales
## W = 0.78969, p-value < 2.2e-16
cat("Keputusan:",
    ifelse(testsales$p.value < 0.05,
          "H0 ditolak, sehingga dapat diambil kesimpulan bahwa data sales tidak berdistribusi normal",
          "H0 gagal ditolak, sehingga dapat diambil kesimpulan bahwa data sales berdistribusi normal"), "\n")
## Keputusan: H0 ditolak, sehingga dapat diambil kesimpulan bahwa data sales tidak berdistribusi normal

Berdasarkan hasil output Uji Shapiro-Wilk di atas, dapat diketahui apakah variabel Profit dan Sales mengikuti pola distribusi normal atau tidak dengan melihat nilai p-value. Karena p-value yang dihasilkan lebih kecil dari 0,05, maka data tersebut dinyatakan tidak berdistribusi normal. Sehingga uji yang akan dilakukan nantinya sebaiknya menggunakan uji non-parametrik

Selain dengan Uji normalitas, dapat juga diketahui berdistribusi normal atau tidak dengan melihat histogram distribusi variabel tersebut.

dist_profit <- dbGetQuery(con3, "SELECT Profit FROM facttable;")
ggplot(dist_profit, aes(x = Profit)) +
  geom_histogram(binwidth = 10, fill = "seagreen3", color = "white", alpha = 1) +
  theme_minimal() +
  labs(title = "Distribusi Variabel Profit",
       x = "Profit",
       y = "Frekuensi") +
  theme(plot.title = element_text(hjust = 0.5)) # memindah judul ke tengah

A. Budget VS Actual

Bagaimana perbandingan antara budget profit dan actual profit dari waktu ke waktu?

Untuk menjawab pertanyaan tersebut, dapat dilakukan analisis terhadap data budget dan actual profit yang ditampilkan dalam bentuk visualisasi. Dengan menggunakan data yang telah diambil dari database, perbandingan antara keduanya dapat dibuat dalam bentuk line chart untuk melihat tren serta perbedaan yang terjadi setiap bulannya. Berikut merupakan sintaks yang digunakan untuk menghasilkan visualisasi tersebut.

budgetvsactual_profit <- dbGetQuery(con3, "SELECT DATE_FORMAT(Date, '%b %Y') AS Month, SUM(`Budget Profit`) AS total_budget_profit,
SUM(Profit) AS total_profit_Actual
FROM facttable
GROUP BY Month
ORDER BY MIN(Date) ASC;")

budgetvsactual_profit$Month <- as.Date(paste("01", budgetvsactual_profit$Month), "%d %b %Y")
ggplot(budgetvsactual_profit, aes(x = Month)) +
  geom_line(aes(y = total_budget_profit, color = "Budget"), linewidth = 1) +
  geom_line(aes(y = total_profit_Actual, color = "Actual"), linewidth = 1) +
  scale_color_manual(values = c("Budget" = "orange", "Actual" = "pink")) +
  scale_x_date(date_labels = "%b %Y", date_breaks = "2 month") +
  theme_minimal() +
  labs(title = "Tren Budget vs Actual (Profit)",
       x = "Bulan",
       y = "Total Profit",
       color = "Keterangan") +
  theme(plot.title = element_text(hjust = 0.5),
        axis.text.x = element_text(angle = 45, hjust = 1))

Pada linechart tersebut, dapat diketahui bagaimana progress/perkembangan target profit (budget) dengan profit yang terealisasikan (aktual) selama periode 24 bulan. Jika dianalisis lebih dalam, dapat terlihat bahwa profit aktual seringkali berada di atas atau mendekati target, yang berarti performa profit cukup baik meskipun pada 12 bulan awal profit aktual lebih rendah dibandingkan budget profitnya.

B. Sales ~ Produk

Bagaimana total sales pada masing-masing produk selama 24 bulan?

Distribusi total penjualan pada setiap produk dapat dianalisis dengan mengelompokkan data berdasarkan nama produk dan menjumlahkan nilai sales-nya. Hasil agregasi ini kemudian divisualisasikan dalam bentuk bar chart untuk memudahkan perbandingan antar produk. Melalui visualisasi ini, dapat terlihat produk mana yang memiliki kontribusi penjualan paling tinggi maupun paling rendah. Berikut merupakan sintaks yang digunakan untuk menghasilkan visualisasi tersebut.

total_sales_produk <- dbGetQuery(con3, "SELECT p.product, SUM(f.Sales) as total_sales
FROM facttable f
INNER JOIN product p USING (productId)
GROUP BY p.product
ORDER BY total_sales DESC;")

ggplot(total_sales_produk, aes(x = reorder(product, total_sales), y = total_sales)) +
  geom_bar(stat = "identity", fill = "coral3", alpha = 1) +
  geom_text(aes(label = scales::comma(total_sales)), hjust = -0.1, size = 3.5) +  #menambahkan koma
  scale_y_continuous(labels = scales::comma, limits = c(0, max(total_sales_produk$total_sales) * 1.2)) + #menambahkan koma
  coord_flip() +   #buat jadi horizontal
  theme_minimal() +
  labs(title = "Total Sales Produk",
       x = "Produk",
       y = "Total Sales") +
  theme(plot.title = element_text(hjust = 0.5))

Berdasarkan barchart tersebut, dapat diamati urutan produk dengan total sales tertinggi hingga terendah selama periode 24 bulan. Produk yang berada di paling atas merupakan produk dengan total sales tertinggi, sementara produk yang berada di posisi paling bawah merupakan produk dengan total sales terendah. Perbedaan panjang batang antara produk paling atas dengan produk paling bawah menandakan terdapat produk yang lebih dominan dibeli dibanding diantara produk-produk yang ada.

C. Profit ~ Location

Wilayah/Area apa saja yang memiliki total profit tertinggi selama 24 bulan?

Analisis ini bertujuan untuk mengidentifikasi wilayah yang memiliki profit paling konsisten dan signifikan selama periode 24 bulan dalam dataset coffee chain. Data dikelompokkan berdasarkan negara bagian (State), pasar (Market), dan ukuran pasar (Market Size) untuk menjumlahkan akumulasi profit yang dihasilkan kemudian divisualisasikan menggunakan barchart untuk mempermudah penyampaian informasi. Berikut sintaks yang digunakan untuk membuat barchart tersebut

total_profit_area <- dbGetQuery(con3, "SELECT l.State, l.Market, l.`Market Size`, SUM(f.Profit) as total_profit
FROM facttable f
INNER JOIN location l USING (`Area Code`)
GROUP BY l.State, l.Market, l.`Market Size`
ORDER BY total_profit DESC
LIMIT 5;")

ggplot(total_profit_area, aes(x = reorder(State, -total_profit), y = total_profit)) +
  geom_bar(stat = "identity", fill = "turquoise", alpha = 1) +
  geom_text(aes(label = scales::comma(total_profit)), hjust = 0.5, vjust = -0.5, size = 3.5) +
  scale_y_continuous(limits = c(0, max(total_profit_area$total_profit) * 1.2)) +
  theme_minimal() +
  labs(title = "Top 5 Area dengan Profit Tertinggi",
       x = "State",
       y = "Total Profit") +
  theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(hjust = 0.5))

Barchart tersebut menunjukkan lima wilayah (state) dengan profit tertinggi diantara wilayah (state) lainnya selama periode 24 bulan. Lima wilayah dengan profit tertinggi yakni California, Illinois, Lowa, New York, dan Colorado. Dengan mengetahui hal ini, proses produksi/distribusi dapat difokuskan ke lima wilayah tersebut.

Apakah terdapat perbedaan yang signifikan jika dilihat berdasarkan Market Size?

Meskipun secara visual telah diketahui wilayah mana saja yang memiliki profit tertinggi, dapat dipastikan kembali perbedaan profit antar wilayah dengan Uji Mann-Whitney. Karena terdapat 2 kategori market size (ukuran pasar) maka dapat di uji apakah terdapat perbedaan profit antar market size.

# H0 : Tidak terdapat perbedaan profit antar market size
# H0 : Terdapat perbedaan profit antar market size
testmw <- wilcox.test(testtable$Profit[testtable$`Market Size` == "Small Market"],
                      testtable$Profit[testtable$`Market Size` == "Major Market"],
            paired = FALSE, correct = TRUE)
print(testmw)
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  testtable$Profit[testtable$`Market Size` == "Small Market"] and testtable$Profit[testtable$`Market Size` == "Major Market"]
## W = 1359889, p-value < 2.2e-16
## alternative hypothesis: true location shift is not equal to 0
cat("Keputusan:",
    ifelse(testmw$p.value < 0.05,
           "H0 ditolak, sehingga dapat diambil kesimpulan bahwa terdapat perbedaan profit antar market size",
           "H0 gagal ditolak, sehingga dapat diambil kesimpulan bahwa tidak terdapat perbedaan profit antara market size"), "\n")
## Keputusan: H0 ditolak, sehingga dapat diambil kesimpulan bahwa terdapat perbedaan profit antar market size

Berdasarkan hasil output dari Uji Mann-Whitney di atas, keputusan diambil dengan melihat nilai p-value yang dibandingkan dengan taraf signifikansi 0,05. Jika p-value yang dihasilkan kurang dari 0,05, maka dapat disimpulkan bahwa terdapat perbedaan nilai keuntungan (profit) antara kategori Small Market dan Major Market. Hasil pengujian ini memberikan kepastian bahwa pengelompokan berdasarkan market size memang memiliki pengaruh terhadap besar kecilnya profit yang tercatat.

Jika dilakukan dengan uji t.test:

ttest1 <- t.test(Profit ~ `Market Size`, var.equal = TRUE, data = testtable)
print(ttest1)
## 
##  Two Sample t-test
## 
## data:  Profit by Market Size
## t = 16.382, df = 4246, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group Major Market and group Small Market is not equal to 0
## 95 percent confidence interval:
##  44.53533 56.64413
## sample estimates:
## mean in group Major Market mean in group Small Market 
##                   91.39437                   40.80464
cat("Keputusan:",
    ifelse(ttest1$p.value < 0.05,
           "H0 ditolak, sehingga dapat diambil kesimpulan bahwa terdapat perbedaan profit antar market size",
           "H0 gagal ditolak, sehingga dapat diambil kesimpulan bahwa tidak terdapat perbedaan profit antara market size"), "\n")
## Keputusan: H0 ditolak, sehingga dapat diambil kesimpulan bahwa terdapat perbedaan profit antar market size

Baik dilakukan dengan uji Mann-Whitney maupun uji ttest, keduanya menghasilkan p-value yang kurang dari 0.05 sehingga H0 ditolak.

Agar penyampaian total profit berdasarkan market size (ukuran pasar) lebih informatif, dapat menggunakan visualisasi berupa barchart berikut.

profit_marketsize <- dbGetQuery(con3, "SELECT SUM(f.Profit) as total_profit, l.`Market Size`
FROM facttable f
INNER JOIN location l USING (`Area Code`)
GROUP BY l.`Market Size`;")
ggplot(profit_marketsize, aes(x = reorder(`Market Size`, -total_profit), y = total_profit)) +
  geom_bar(stat = "identity", fill = c("palevioletred", "orchid"), alpha = 1) +
  geom_text(aes(label = scales::comma(total_profit)), hjust = 0.5, vjust = -0.5, size = 3.5) +
  scale_y_continuous(limits = c(0, max(profit_marketsize$total_profit) * 1.2)) +
  theme_minimal() +
  labs(title = "Profit Berdasarkan Market size",
       x = "Market size",
       y = "Profit") +
  theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(hjust = 0.5))

D. Profit ~ Tipe Produk

Apakah terdapat perbedaan total profit yang signifikan berdasarkan tipe produk?

Selain menganalisis profit berdasarkan wilayah, perlu juga dilakukan analisis profit berdasarkan tipe produk untuk melihat apakah kategori tipe produk juga memiliki pengaruh terhadap total keuntungan/profit. Karena data profit akan dikelompokkan ke dalam beberapa tipe produk yang berbeda dan merupakan data berdistribusi tidak normal, maka uji yang digunakan adalah Uji Kruskal-Wallis.

# H0 : Tidak terdapat perbedaan profit antar tipe produk (sA = sB = sC = sD)
# H1 : Terdapat perbedaan profit antar tipe produk (sA != sB != sC != sD)
testkw <- kruskal.test(Sales ~ `Product Type`, data = testtable)
print(testkw)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  Sales by Product Type
## Kruskal-Wallis chi-squared = 41.245, df = 3, p-value = 5.802e-09
cat("Keputusan:",
    ifelse(testkw$p.value < 0.05,
           "H0 ditolak, sehingga dapat diambil kesimpulan bahwa terdapat perbedaan sales antar tipe produk",
           "H0 gagal ditolak, sehingga dapat diambil kesimpulan bahwa tidak terdapat perbedaan sales antar tipe produk"), "\n")
## Keputusan: H0 ditolak, sehingga dapat diambil kesimpulan bahwa terdapat perbedaan sales antar tipe produk

Berdasarkan hasil Uji Kruskal-Wallis di atas, keputusan diambil dengan memperhatikan nilai p-value yang dibandingkan dengan taraf signifikansi 0.05. Karena p-value lebih kecil dari 0.05, maka dapat disimpulkan bahwa terdapat perbedaan nilai keuntungan (profit) yang signifikan di antara kategori-kategori tipe produk yang ada. Hasil ini membuktikan bahwa jenis atau tipe produk memberikan pengaruh yang berbeda terhadap profit yang diperoleh.

E. Sales ~ Tipe Produk

Berapa persentase sales dari setiap tipe produk?

Untuk melengkapi hasil uji sebelumnya, maka dilakukan visualisasi data dalam bentuk pie chart guna melihat persentase sales dari masing-masing tipe produk. Dengan menghitung total penjualan per kategori selama periode 24 bulan dan mengubahnya ke dalam bentuk persentase, informasi akan lebih mudah tersampaikan.

total_sales_tipe_produk <- dbGetQuery(con3, "SELECT p.`Product Type`, SUM(f.Sales) as total_sales
FROM facttable f
INNER JOIN product p USING (productId)
GROUP BY p.`Product Type`
ORDER BY total_sales DESC;")

persen <- round(total_sales_tipe_produk$total_sales/sum(total_sales_tipe_produk$total_sales) *100, 2)
ggplot(data=total_sales_tipe_produk,
       mapping=aes(x="", y=total_sales, fill=`Product Type`)) +
  geom_bar(stat="identity", width=1) + coord_polar("y") +
  geom_text(aes(label = paste0(persen, "%")),
            position = position_stack(vjust = 0.5)) +
  scale_fill_manual(values=c("tan", "rosybrown4", "yellowgreen", "lightgoldenrod")) + 
  labs(x = NULL, y = NULL, fill = NULL, title = "Persentase Sales Tipe Produk") + 
  theme_classic() + theme(axis.line = element_blank(),
                          axis.text = element_blank(),
                          axis.ticks = element_blank(),
                          plot.title = element_text(hjust = 0.5, color = "Black"))

F. Profit & Sales

Apakah terdapat hubungan yang signifikan antara sales dengan profit yang diperoleh?

Dalam analisis data ini, dilakukan pengujian untuk mengetahui apakah angka penjualan memiliki kaitan dengan keuntungan yang didapatkan. Untuk membuktikannya, digunakan Korelasi Spearman karena diketahui data profit dan sales tidak berdistribusi normal. Pengujian ini akan menunjukkan apakah setiap kenaikan jumlah penjualan selalu diikuti dengan kenaikan profit secara konsisten. Berikut merupakan sintaks yang digunakan untuk melakukan pengujian tersebut.

# H0 : Tidak terdapat hubungan antara profit dengan sales
# H1 : Terdapat hubungan antara profit dengan sales

testks <- cor.test(testtable$Profit, testtable$Sales, method = "spearman")
print(testks)
## 
##  Spearman's rank correlation rho
## 
## data:  testtable$Profit and testtable$Sales
## S = 2909365515, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##       rho 
## 0.7722827
cat("Keputusan:",
    ifelse(testks$p.value < 0.05,
           "H0 ditolak, sehingga dapat diambil kesimpulan bahwa terdapat hubungan antara profit dengan sales",
           "H0 gagal ditolak, sehingga dapat diambil kesimpulan bahwa tidak terdapat hubungan antara profit dengan sales"), "\n")
## Keputusan: H0 ditolak, sehingga dapat diambil kesimpulan bahwa terdapat hubungan antara profit dengan sales

Berdasarkan hasil uji korelasi di atas, keputusan diambil dengan melihat nilai p-value dan koefisien korelasi (rho). Karena nilai p-value lebih kecil dari 0.05, maka kesimpulannya adalah terdapat hubungan antara sales dan profit. Nilai koefisien yang dihasilkan menunjukkan seberapa kuat hubungan tersebut (semakin mendekati angka 1, maka hubungannya semakin searah dan kuat). Hal ini membuktikan bahwa tinggi rendahnya angka penjualan (sales) memang berpengaruh langsung terhadap hasil profit yang ada.