บทที่ 2 การสร้างกราฟและแดชบอร์ดด้วย R
# สำหรับสร้างกราฟ
# ใน R มีระบบกราฟิกพื้นฐาน (base graphics) อยู่แล้ว และเราได้ติดตั้งไลบรารีเสริม ggplot2 และ readxl
# install.packages("ggplot2", repos="https://cloud.r-project.org")
# install.packages("readxl", repos="https://cloud.r-project.org")
#Config ฟอนต์
# ใน Windows สามารถใช้ windowsFonts() เพื่อลงทะเบียนฟอนต์ภาษาไทยได้
if (.Platform$OS.type == "windows") {
windowsFonts(Sarabun = windowsFont("TH Sarabun New"))
# ตั้งค่ากราฟิกพื้นฐานให้ใช้ฟอนต์ Sarabun
par(family = "Sarabun", cex.main = 1.5, cex.lab = 1.2, cex.axis = 1.1)
}
#อ่านข้อมูลจากไฟล์ csv
x <- read.csv('data/customer.csv', stringsAsFactors = FALSE)
x
## item age sex education_level occupation total_spend
## 1 1 25 หญิง ปริญญาตรี พนักงานขาย 4500
## 2 2 27 ชาย ปริญญาโท พนักงานขาย 6200
## 3 3 23 ชาย ปริญญาตรี พนักงานขาย 5000
## 4 4 35 หญิง ปริญญาเอก พนักงานขาย 8000
## 5 5 41 ชาย ปริญญาโท พนักงานขาย 120000
## 6 6 32 หญิง ปริญญาตรี พนักงานขาย 3500
## 7 7 26 หญิง ปริญญาโท พนักงานขาย 11000
## 8 8 22 ชาย ปริญญาตรี พนักงานขาย 8750
## 9 9 28 ชาย พนักงานขาย 15000
## 10 10 34 ชาย ปริญญาตรี พนักงานขาย 12000
#การสร้างกราฟแท่ง (Bar Chart)
x <- read.csv('data/customer.csv', stringsAsFactors = FALSE)
# นับจำนวนของแต่ละเพศ
sex_counts <- table(x$sex)
data <- data.frame(จำนวน = as.vector(sex_counts), row.names = names(sex_counts))
# วาดกราฟแท่ง
barplot(data$จำนวน,
names.arg = rownames(data),
main = 'เปรียบเทียบจำนวนเพศชายกับเพศหญิง',
ylab = 'จำนวน',
col = 'skyblue')

data
## จำนวน
## ชาย 6
## หญิง 4
#การสร้างกราฟวงกลม (Pie Chart)
edu_counts <- table(x$education_level)
data <- data.frame(จำนวน = as.vector(edu_counts), row.names = names(edu_counts))
# คำนวณเปอร์เซ็นต์สำหรับป้ายกำกับของวงกลม
pct <- round(100 * data$จำนวน / sum(data$จำนวน), 2)
lbls <- paste0(rownames(data), "\n", pct, "%")
pie(data$จำนวน,
labels = lbls,
col = rainbow(length(edu_counts)))

data
## จำนวน
## 1
## ปริญญาตรี 5
## ปริญญาโท 3
## ปริญญาเอก 1
#การสร้างกราฟเส้น (Line Chart)
data <- data.frame(age = x$age)
plot(data$age,
type = 'l', # Line only
main = 'เปรียบเทียบอายุของลูกค้า',
xlab = 'คนที่',
ylab = 'อายุ',
col = 'blue')

#การสร้างฮิสโทแกรม (Histogram)
data <- data.frame(age = x$age)
hist(data$age,
breaks = 5,
main = 'ฮิสโทแกรมของอายุลูกค้า',
xlab = 'อายุ',
ylab = 'จำนวนคน',
col = 'lightgreen')

#การสร้างบ๊อกพล็อต (Boxplot)
#ขอบล่าง ค่า Min หรือ Q1−1.5×IQR | IQR = Q3 - Q1
#ขอบบน ค่า Max หรือ Q3+1.5×IQR | IQR = Q3 - Q1
data <- data.frame(age = x$age)
boxplot(data$age,
main = 'บ๊อกพล๊อตของอายุลูกค้า',
names = c('age'),
col = 'gold')

#แสดงสถิติเบื้องต้นของข้อมูล
summary(data)
## age
## Min. :22.00
## 1st Qu.:25.25
## Median :27.50
## Mean :29.30
## 3rd Qu.:33.50
## Max. :41.00
#การสร้างสแคทเทอร์ (Scatter)
data <- x[, c('age', 'total_spend')]
plot(data$age, data$total_spend,
main = 'สแคทเทอร์แสดงความสัมพันธ์ระหว่างอายุกับยอดการใช้จ่าย',
xlab = 'age',
ylab = 'total_spend',
col = 'darkred',
pch = 19)

#อ่านข้อมูลอัตราการยกเลิกการเป็นสมาชิกจากไฟล์ excel
library(readxl)
df <- read_excel('data/churn_rate.xlsx')
df
## # A tibble: 10 × 6
## item age sex education_level occupation churn
## <dbl> <chr> <chr> <chr> <chr> <chr>
## 1 1 22-25 หญิง ปริญญาตรี พนักงานขาย ยกเลิก
## 2 2 26-31 ชาย ปริญญาโท พนักงานบัญชี ไม่ยกเลิก
## 3 3 22-25 ชาย ปริญญาตรี พนักงานขาย ยกเลิก
## 4 4 32-41 หญิง ปริญญาเอก พนักงานบุคคล ไม่ยกเลิก
## 5 5 32-41 ชาย ปริญญาโท พนักงานบัญชี ไม่ยกเลิก
## 6 6 32-41 หญิง ปริญญาตรี พนักงานบัญชี ยกเลิก
## 7 7 26-31 หญิง ปริญญาโท พนักงานขาย ไม่ยกเลิก
## 8 8 22-25 ชาย ปริญญาตรี พนักงานบุคคล ยกเลิก
## 9 9 26-31 ชาย ปริญญาตรี พนักงานบุคคล ไม่ยกเลิก
## 10 10 32-41 ชาย ปริญญาตรี พนักงานขาย ไม่ยกเลิก
library(readxl)
# อ่านข้อมูลจากไฟล์ xlsx
df <- read_excel('data/churn_rate.xlsx')
# เตรียม Layout 2x2
par(mfrow=c(2, 2), mar=c(5, 6, 4, 2) + 0.1)
# กราฟที่ 1: Churn by Age Group (Stacked Bar)
age_churn_table <- table(df$churn, df$age)
barplot(age_churn_table, horiz = TRUE,
col = c('#ef4444', '#22c55e'), main = 'Churn by Age Group',
xlab = 'จำนวนลูกค้า', las = 1, legend = rownames(age_churn_table))
# กราฟที่ 2: Churn by Education Level (Stacked Bar)
edu_churn_table <- table(df$churn, df$education_level)
barplot(edu_churn_table, horiz = TRUE,
col = c("#f76868", "#22c55e"), main = 'Churn by Education Level',
xlab = 'จำนวนลูกค้า', las = 1, legend = rownames(edu_churn_table))
# ฟังก์ชันผู้ช่วยสำหรับสร้าง Heatmap สวยๆ ด้วย base R
plot_heatmap <- function(tab, main_title) {
mat <- as.matrix(tab)
# กลับลำดับแถวเพื่อให้แสดงผลจากบนลงล่าง
mat <- mat[nrow(mat):1, , drop=FALSE]
cols <- colorRampPalette(c("#fff5f0", "#fc9272", "#cb181d"))(100)
image(1:ncol(mat), 1:nrow(mat), t(mat),
col = cols, axes = FALSE, xlab = "", ylab = "", main = main_title)
axis(1, at = 1:ncol(mat), labels = colnames(mat))
axis(2, at = 1:nrow(mat), labels = rownames(mat), las = 1)
# ใส่ตัวเลขแสดงจำนวนในแต่ละช่อง
for (x_val in 1:ncol(mat)) {
for (y_val in 1:nrow(mat)) {
text(x_val, y_val, labels = mat[y_val, x_val],
col = ifelse(mat[y_val, x_val] > mean(mat), "white", "black"), cex = 1.2)
}
}
box()
}
# กราฟที่ 3: Age Group vs Churn Status (Heatmap)
age_churn_crosstab <- table(df$age, df$churn)
plot_heatmap(age_churn_crosstab, 'Age Group vs Churn Status')
# กราฟที่ 4: Education Level vs Churn Status (Heatmap)
edu_churn_crosstab <- table(df$education_level, df$churn)
plot_heatmap(edu_churn_crosstab, 'Education Level vs Churn Status')

#อ่านข้อมูล pm2.5 จากไฟล์ excel
library(readxl)
df <- read_excel('data/pm2.5.xlsx')
df
## # A tibble: 10 × 4
## Date Temperature Rainfall PM2.5
## <dttm> <dbl> <dbl> <dbl>
## 1 2568-08-16 00:00:00 35 18 22
## 2 2568-08-17 00:00:00 34 15.2 25
## 3 2568-08-18 00:00:00 33 8.5 28
## 4 2568-08-19 00:00:00 34 2 26
## 5 2568-08-20 00:00:00 35 0 24
## 6 2568-08-21 00:00:00 32 12.3 30
## 7 2568-08-22 00:00:00 31 10.4 33
## 8 2568-08-23 00:00:00 29 0.5 39
## 9 2568-08-24 00:00:00 30 0 38
## 10 2568-08-25 00:00:00 28 10.7 34
library(readxl)
# อ่านข้อมูลจากไฟล์ xlsx
df <- read_excel('data/pm2.5.xlsx')
# ตั้งค่า Layout 2x2
par(mfrow=c(2, 2), mar=c(5, 5, 4, 2) + 0.1)
# กราฟที่ 1: PM2.5 Trend (Line + Markers + Threshold Lines)
plot(df$Date, df$PM2.5, type = 'o', col = '#e74c3c', pch = 19,
main = 'PM2.5 Trend', xlab = 'Date', ylab = 'PM2.5 (µg/m³)')
abline(h = 25, col = 'orange', lty = 2, lwd = 2)
abline(h = 37.5, col = 'red', lty = 2, lwd = 2)
legend('topright', legend = c('Standard (25 µg/m³)', 'Unhealthy (37.5 µg/m³)'),
col = c('orange', 'red'), lty = 2, lwd = 2)
grid(nx = NULL, ny = NULL, col = "lightgray", lty = "dotted")
# คำนวณสีตามระดับ PM2.5 (เขียว -> เหลือง -> แดง)
color_palette <- colorRampPalette(c("#2ca02c", "#ffbb78", "#d62728"))(100)
pm_min <- min(df$PM2.5)
pm_max <- max(df$PM2.5)
pm_scaled <- round(1 + 99 * (df$PM2.5 - pm_min) / (pm_max - pm_min))
mapped_colors <- color_palette[pm_scaled]
# กราฟที่ 2: PM2.5 vs Temperature (Scatter + Trend Line)
plot(df$Temperature, df$PM2.5, col = "black", bg = mapped_colors,
pch = 21, cex = 2, main = 'PM2.5 vs Temperature',
xlab = 'Temperature', ylab = 'PM2.5')
fit1 <- lm(PM2.5 ~ Temperature, data = df)
abline(fit1, col = "#ff8080", lty = 2, lwd = 2)
legend("topright", legend=c("High PM2.5", "Low PM2.5"), fill=c("#d62728", "#2ca02c"))
grid(nx = NULL, ny = NULL, col = "lightgray", lty = "dotted")
# กราฟที่ 3: PM2.5 vs Rainfall (Scatter + Trend Line)
plot(df$Rainfall, df$PM2.5, col = "black", bg = mapped_colors,
pch = 21, cex = 2, main = 'PM2.5 vs Rainfall',
xlab = 'Rainfall', ylab = 'PM2.5')
fit2 <- lm(PM2.5 ~ Rainfall, data = df)
abline(fit2, col = "#ff8080", lty = 2, lwd = 2)
legend("topright", legend=c("High PM2.5", "Low PM2.5"), fill=c("#d62728", "#2ca02c"))
grid(nx = NULL, ny = NULL, col = "lightgray", lty = "dotted")
# กราฟที่ 4: All Parameters Comparison (Multi-line)
ylim_range <- range(c(df$Temperature, df$Rainfall, df$PM2.5), na.rm = TRUE)
plot(df$Date, df$Temperature, type = 'o', col = 'blue', pch = 19, cex = 0.8,
ylim = ylim_range, main = 'All Parameters Comparison', xlab = 'Date', ylab = 'Value')
lines(df$Date, df$Rainfall, type = 'o', col = 'green', pch = 15, cex = 0.8)
lines(df$Date, df$PM2.5, type = 'o', col = 'red', pch = 17, cex = 0.8)
legend('topright', legend = c('Temperature (°C)', 'Rainfall (mm)', 'PM2.5 (µg/m³)'),
col = c('blue', 'green', 'red'), pch = c(19, 15, 17), lty = 1)
grid(nx = NULL, ny = NULL, col = "lightgray", lty = "dotted")
