1. Өгөгдөл ачаалах ба бэлтгэх
1.1 Сангууд ачаалах
library(readxl)
library(ggplot2)
library(dplyr)
library(tidyr)
library(e1071) # skewness, kurtosis
library(scales) # тоон формат
1.2 Өгөгдөл унших
menu <- read_excel("KFC_Mongolia_Data.xlsx", sheet = "Меню")
categories <- read_excel("KFC_Mongolia_Data.xlsx", sheet = "Ангилалууд")
branches <- read_excel("KFC_Mongolia_Data.xlsx", sheet = "Салбарууд")
# Баганы нэрсийг тохируулах
colnames(menu) <- c("id", "category_mn", "category_en", "name_mn", "name_en",
"price", "type", "combo", "description", "image_url", "rank")
colnames(branches) <- c("id", "name_mn", "name_en", "branch_code", "address",
"lat", "lng", "image_url")
1.3 Өгөгдөл бэлтгэх
# Үнийн ангилал нэмэх
menu <- menu %>%
mutate(
price_category = case_when(
price < 3000 ~ "Хямд",
price <= 10000 ~ "Дунд",
price > 10000 ~ "Үнэтэй"
),
price_category = factor(price_category, levels = c("Хямд", "Дунд", "Үнэтэй"))
)
# Салбаруудын координат цэвэрлэх (NA хасах)
branches_geo <- branches %>%
filter(!is.na(lat) & !is.na(lng)) %>%
mutate(lat = as.numeric(lat), lng = as.numeric(lng))
# Өгөгдлийн эхний мөрүүдийг харах
head(menu %>% select(name_en, category_en, price, price_category), 10)
## # A tibble: 10 × 4
## name_en category_en price price_category
## <chr> <chr> <dbl> <fct>
## 1 EGG TART 2PIECES DESSERTS 5500 Дунд
## 2 VANILLA ICECREAM DESSERTS 1500 Хямд
## 3 CHEESE WEDGES T SIDES 6500 Дунд
## 4 KIDS SET 1 T SET ITEMS 8000 Дунд
## 5 KIDS SET 2 T SET ITEMS 8500 Дунд
## 6 2 PCS CHEESECAKE BALL SIDES 6900 Дунд
## 7 FILLET BOXMASTER SINGLE ITEMS 12000 Үнэтэй
## 8 ZINGER BOXMASTER SINGLE ITEMS 12000 Үнэтэй
## 9 BOXMASTER COMBO T MINI COMBO 15000 Үнэтэй
## 10 BOXMASTER X-MEAL T X-MEAL BUNDLES 21500 Үнэтэй
2. Тодорхойлогч статистикууд (Descriptive Statistics)
2.1 Measures of Location
# Mode функц
get_mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
price <- menu$price
stats_location <- data.frame(
Measure = c("Дундаж (Mean)", "Медиан (Median)", "Мод (Mode)",
"Тайрсан дундаж 10% (Trimmed Mean)",
"Геометр дундаж (Geometric Mean)",
"Mid-range", "Trimean",
"Q1 (25-р перцентиль)", "Q3 (75-р перцентиль)"),
Value = c(
round(mean(price), 0),
round(median(price), 0),
get_mode(price),
round(mean(price, trim = 0.1), 0),
round(exp(mean(log(price))), 0),
round((min(price) + max(price)) / 2, 0),
round((quantile(price, 0.25) + 2 * median(price) + quantile(price, 0.75)) / 4, 0),
round(quantile(price, 0.25), 0),
round(quantile(price, 0.75), 0)
)
)
knitr::kable(stats_location, caption = "Байршлын хэмжүүрүүд (Measures of Location)")
Байршлын хэмжүүрүүд (Measures of Location)
| Дундаж (Mean) |
8328 |
| Медиан (Median) |
6500 |
| Мод (Mode) |
1500 |
| Тайрсан дундаж 10% (Trimmed Mean) |
7074 |
| Геометр дундаж (Geometric Mean) |
5270 |
| Mid-range |
25750 |
| Trimean |
6688 |
| Q1 (25-р перцентиль) |
2000 |
| Q3 (75-р перцентиль) |
11750 |
2.2 Measures of Dispersion
stats_dispersion <- data.frame(
Measure = c("Хүрээ (Range)", "IQR (Интерквартиль хүрээ)",
"Дисперс (Variance)", "Стандарт хазайлт (Std Dev)",
"Вариацын коэффициент (CV%)"),
Value = c(
paste(min(price), "-", max(price), "=", max(price) - min(price)),
round(IQR(price), 0),
round(var(price), 0),
round(sd(price), 0),
paste0(round(sd(price) / mean(price) * 100, 1), "%")
)
)
knitr::kable(stats_dispersion, caption = "Тархалтын хэмжүүрүүд (Measures of Dispersion)")
Тархалтын хэмжүүрүүд (Measures of Dispersion)
| Хүрээ (Range) |
1000 - 50500 = 49500 |
| IQR (Интерквартиль хүрээ) |
9750 |
| Дисперс (Variance) |
72965523 |
| Стандарт хазайлт (Std Dev) |
8542 |
| Вариацын коэффициент (CV%) |
102.6% |
2.3 Measures of Shape
stats_shape <- data.frame(
Measure = c("Хазайлт (Skewness)", "Тэгш бус байдал (Kurtosis)"),
Value = c(round(skewness(price), 3), round(kurtosis(price), 3)),
Interpretation = c(
ifelse(skewness(price) > 0, "Баруун тийш хазайсан (right-skewed)",
"Зүүн тийш хазайсан (left-skewed)"),
ifelse(kurtosis(price) > 0, "Leptokurtic (шовх)", "Platykurtic (тэгш)")
)
)
knitr::kable(stats_shape, caption = "Хэлбэрийн хэмжүүрүүд (Measures of Shape)")
Хэлбэрийн хэмжүүрүүд (Measures of Shape)
| Хазайлт (Skewness) |
2.653 |
Баруун тийш хазайсан (right-skewed) |
| Тэгш бус байдал (Kurtosis) |
10.138 |
Leptokurtic (шовх) |
3. Категориал хувьсагчийн графикууд
3.1 Simple Bar Chart — Ангилал тус бүрийн бүтээгдэхүүний тоо
cat_counts <- menu %>%
count(category_en) %>%
arrange(desc(n))
ggplot(cat_counts, aes(x = reorder(category_en, -n), y = n)) +
geom_bar(stat = "identity", fill = "#E4002B", alpha = 0.85) +
geom_text(aes(label = n), vjust = -0.5, size = 4, fontface = "bold") +
labs(title = "KFC Mongolia: Ангилал тус бүрийн бүтээгдэхүүний тоо",
subtitle = "Simple Bar Chart",
x = "Ангилал (Category)", y = "Тоо (Count)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

3.2 Stacked Bar Chart — Ангилал дотор үнийн ангилал
ggplot(menu, aes(x = category_en, fill = price_category)) +
geom_bar(stat = "count") +
scale_fill_manual(values = c("Хямд" = "#4CAF50", "Дунд" = "#FF9800", "Үнэтэй" = "#E4002B")) +
labs(title = "KFC Mongolia: Ангилал дотор үнийн ангилал",
subtitle = "Stacked Bar Chart",
x = "Ангилал", y = "Тоо", fill = "Үнийн ангилал") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

3.3 Grouped Bar Chart — Ангилал + үнийн ангилал (dodge)
ggplot(menu, aes(x = category_en, fill = price_category)) +
geom_bar(stat = "count", position = "dodge") +
scale_fill_manual(values = c("Хямд" = "#4CAF50", "Дунд" = "#FF9800", "Үнэтэй" = "#E4002B")) +
labs(title = "KFC Mongolia: Ангилал + Үнийн ангилал",
subtitle = "Grouped Bar Chart (position = dodge)",
x = "Ангилал", y = "Тоо", fill = "Үнийн ангилал") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

3.4 Spine Plot — Ангилал бүрийн пропорц
ggplot(menu, aes(x = category_en, fill = price_category)) +
geom_bar(position = "fill") +
scale_fill_manual(values = c("Хямд" = "#4CAF50", "Дунд" = "#FF9800", "Үнэтэй" = "#E4002B")) +
scale_y_continuous(labels = percent_format()) +
labs(title = "KFC Mongolia: Ангилал бүрийн үнийн пропорц",
subtitle = "Spine Plot (position = fill)",
x = "Ангилал", y = "Пропорц", fill = "Үнийн ангилал") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

3.5 Pie Chart — Ангилалын эзлэх хувь
pie_data <- menu %>%
count(category_en) %>%
arrange(desc(n)) %>%
mutate(
pct = round(n / sum(n) * 100, 1),
label = paste0(category_en, "\n", n, " (", pct, "%)")
)
ggplot(pie_data, aes(x = "", y = n, fill = category_en)) +
geom_bar(stat = "identity", width = 1) +
coord_polar(theta = "y", start = 0) +
geom_text(aes(label = paste0(pct, "%")),
position = position_stack(vjust = 0.5), size = 3) +
labs(title = "KFC Mongolia: Ангилалын эзлэх хувь",
subtitle = "Pie Chart",
fill = "Ангилал") +
theme_void() +
scale_fill_brewer(palette = "Set3")

4. Тасралтгүй хувьсагчийн графикууд
4.1 Dot Plot (Jittered) — Үнийн тархалт
ggplot(menu, aes(x = price, y = 0)) +
geom_jitter(height = 0.2, size = 3, alpha = 0.7, color = "#E4002B") +
labs(title = "KFC Mongolia: Бүтээгдэхүүний үнийн тархалт",
subtitle = "Jittered Dot Plot",
x = "Үнэ (₮)") +
scale_x_continuous(labels = comma_format()) +
theme_minimal() +
theme(axis.text.y = element_blank(), axis.title.y = element_blank(),
axis.ticks.y = element_blank())

4.2 Wilkinson Dot Plot — Үнийн тархалт
ggplot(menu, aes(x = price)) +
geom_dotplot(binwidth = 1500, fill = "#E4002B", color = "white", dotsize = 0.8) +
labs(title = "KFC Mongolia: Үнийн Wilkinson Dot Plot",
subtitle = "Цэг бүр нэг бүтээгдэхүүнийг илэрхийлнэ",
x = "Үнэ (₮)") +
scale_x_continuous(labels = comma_format()) +
theme_minimal() +
theme(axis.text.y = element_blank(), axis.title.y = element_blank())

4.3 Cleveland Dot Plot — Бүтээгдэхүүнүүд үнээр эрэмбэлсэн
ggplot(menu, aes(x = price, y = reorder(name_en, price))) +
geom_point(size = 3, color = "#E4002B") +
labs(title = "KFC Mongolia: Бүтээгдэхүүнүүд үнээр эрэмбэлсэн",
subtitle = "Cleveland Dot Plot",
x = "Үнэ (₮)", y = "Бүтээгдэхүүн") +
scale_x_continuous(labels = comma_format()) +
theme_minimal() +
theme(axis.text.y = element_text(size = 7))

4.4 Histogram — Үнийн тархалт
ggplot(menu, aes(x = price)) +
geom_histogram(binwidth = 3000, fill = "#E4002B", color = "white", alpha = 0.85) +
geom_vline(aes(xintercept = mean(price)), color = "blue",
linetype = "dashed", linewidth = 1) +
annotate("text", x = mean(menu$price) + 2000, y = Inf,
label = paste("Дундаж =", comma(round(mean(menu$price), 0)), "₮"),
vjust = 2, color = "blue", size = 4) +
labs(title = "KFC Mongolia: Үнийн тархалт",
subtitle = "Histogram (binwidth = 3,000₮)",
x = "Үнэ (₮)", y = "Тоо") +
scale_x_continuous(labels = comma_format()) +
theme_minimal()

4.5 Histogram (Grouped) — Ангилалаар бүлэглэсэн
top_cats <- menu %>%
count(category_en) %>%
filter(n >= 3) %>%
pull(category_en)
menu_top <- menu %>% filter(category_en %in% top_cats)
ggplot(menu_top, aes(x = price, fill = category_en)) +
geom_histogram(binwidth = 3000, position = "dodge", alpha = 0.8) +
labs(title = "KFC Mongolia: Үнийн тархалт ангилалаар",
subtitle = "Grouped Histogram",
x = "Үнэ (₮)", y = "Тоо", fill = "Ангилал") +
scale_x_continuous(labels = comma_format()) +
scale_fill_brewer(palette = "Set2") +
theme_minimal()

4.6 Kernel Density Plot — Үнийн нягтын график
ggplot(menu, aes(x = price)) +
geom_density(fill = "#E4002B", alpha = 0.4, color = "#E4002B", linewidth = 1) +
geom_rug(color = "#E4002B", alpha = 0.5) +
labs(title = "KFC Mongolia: Үнийн нягтын тархалт",
subtitle = "Kernel Density Plot",
x = "Үнэ (₮)", y = "Нягт (Density)") +
scale_x_continuous(labels = comma_format()) +
theme_minimal()

4.7 Box Plot — Ангилал бүрийн үнийн boxplot
ggplot(menu, aes(x = reorder(category_en, price, FUN = median), y = price,
fill = category_en)) +
geom_boxplot(alpha = 0.7, outlier.color = "red", outlier.size = 3) +
stat_summary(fun = mean, geom = "point", shape = 4, size = 3, color = "blue") +
labs(title = "KFC Mongolia: Ангилал бүрийн үнийн тархалт",
subtitle = "Box Plot (x = дундаж, улаан цэг = outlier)",
x = "Ангилал", y = "Үнэ (₮)") +
scale_y_continuous(labels = comma_format()) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.position = "none")

5. Цуваа өгөгдлийн график (Time-series)
5.1 Run Chart — Салбаруудын байршлын өргөрөг
branches_run <- branches_geo %>%
arrange(id) %>%
mutate(index = row_number())
ggplot(branches_run, aes(x = index, y = lat)) +
geom_line(color = "#E4002B", linewidth = 1) +
geom_point(color = "#E4002B", size = 2.5) +
geom_hline(yintercept = mean(branches_run$lat), linetype = "dashed",
color = "blue", linewidth = 0.8) +
annotate("text", x = 1, y = mean(branches_run$lat) + 0.15,
label = paste("Дундаж өргөрөг =", round(mean(branches_run$lat), 2)),
color = "blue", hjust = 0, size = 3.5) +
geom_text(aes(label = name_en), size = 2, vjust = -1, angle = 30) +
labs(title = "KFC Mongolia: Салбаруудын газарзүйн өргөрөг",
subtitle = "Run Chart — салбар нээгдсэн дарааллаар",
x = "Салбарын дугаар", y = "Өргөрөг (Latitude)") +
theme_minimal()

6. Хувьсагч хоорондын хамаарлын графикууд
6.1 Mosaic Plot — Ангилал vs Үнийн ангилал
mosaic_table <- table(menu$category_en, menu$price_category)
mosaicplot(mosaic_table,
main = "KFC Mongolia: Ангилал vs Үнийн ангилал\nMosaic Plot",
xlab = "Ангилал (Category)",
ylab = "Үнийн ангилал (Price Category)",
color = c("#4CAF50", "#FF9800", "#E4002B"),
las = 2,
cex.axis = 0.7)

6.2 Scatter Plot — Салбаруудын газарзүйн байршил
ggplot(branches_geo, aes(x = lng, y = lat)) +
geom_point(size = 4, color = "#E4002B", alpha = 0.8) +
geom_text(aes(label = name_en), size = 2.5, vjust = -1, check_overlap = TRUE) +
labs(title = "KFC Mongolia: Салбаруудын газарзүйн байршил",
subtitle = "Scatter Plot (Уртраг vs Өргөрөг)",
x = "Уртраг (Longitude)", y = "Өргөрөг (Latitude)") +
theme_minimal()

7. Бусад графикууд
7.1 QQ Plot — Үнийн хэвийн тархалтын шалгалт
ggplot(menu, aes(sample = price)) +
stat_qq(color = "#E4002B", size = 3) +
stat_qq_line(color = "blue", linewidth = 1) +
labs(title = "KFC Mongolia: Үнэ хэвийн тархалттай эсэх",
subtitle = "QQ Plot — цэгүүд шулуун дээр байвал хэвийн тархалттай",
x = "Онолын квантиль (Theoretical)", y = "Түүврийн квантиль (Sample)") +
scale_y_continuous(labels = comma_format()) +
theme_minimal()

7.2 Violin Plot — Ангилал бүрийн үнийн тархалт
ggplot(menu_top, aes(x = category_en, y = price, fill = category_en)) +
geom_violin(alpha = 0.6, trim = FALSE) +
geom_boxplot(width = 0.15, fill = "white", alpha = 0.8) +
stat_summary(fun = mean, geom = "point", shape = 4, size = 3, color = "red") +
labs(title = "KFC Mongolia: Ангилал бүрийн үнийн тархалт",
subtitle = "Violin Plot + Box Plot (x = дундаж)",
x = "Ангилал", y = "Үнэ (₮)") +
scale_y_continuous(labels = comma_format()) +
scale_fill_brewer(palette = "Set2") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.position = "none")

8. Outlier шинжилгээ (IQR Rule)
Q1 <- quantile(price, 0.25)
Q3 <- quantile(price, 0.75)
IQR_val <- IQR(price)
lower_bound <- Q1 - 1.5 * IQR_val
upper_bound <- Q3 + 1.5 * IQR_val
cat("=== Outlier шинжилгээ (IQR Rule) ===\n")
## === Outlier шинжилгээ (IQR Rule) ===
cat("Q1:", comma(Q1), "₮\n")
## Q1: 2,000 ₮
cat("Q3:", comma(Q3), "₮\n")
## Q3: 11,750 ₮
cat("IQR:", comma(IQR_val), "₮\n")
## IQR: 9,750 ₮
cat("Доод хязгаар (Q1 - 1.5*IQR):", comma(lower_bound), "₮\n")
## Доод хязгаар (Q1 - 1.5*IQR): -12,625 ₮
cat("Дээд хязгаар (Q3 + 1.5*IQR):", comma(upper_bound), "₮\n\n")
## Дээд хязгаар (Q3 + 1.5*IQR): 26,375 ₮
outliers <- menu %>% filter(price < lower_bound | price > upper_bound)
if (nrow(outliers) > 0) {
cat("Outlier бүтээгдэхүүнүүд:\n")
knitr::kable(outliers %>% select(name_en, category_en, price, price_category),
caption = "IQR Rule-р илэрсэн Outlier-ууд")
} else {
cat("IQR Rule-р outlier илрээгүй.\n")
}
## Outlier бүтээгдэхүүнүүд:
IQR Rule-р илэрсэн Outlier-ууд
| 12PCS CHICKEN T |
SINGLE ITEMS |
50500 |
Үнэтэй |
menu <- menu %>%
mutate(is_outlier = ifelse(price < lower_bound | price > upper_bound,
"Outlier", "Хэвийн"))
ggplot(menu, aes(x = price, y = 0, color = is_outlier)) +
geom_jitter(height = 0.3, size = 4, alpha = 0.8) +
scale_color_manual(values = c("Outlier" = "red", "Хэвийн" = "#E4002B")) +
geom_vline(xintercept = lower_bound, linetype = "dashed", color = "blue") +
geom_vline(xintercept = upper_bound, linetype = "dashed", color = "blue") +
annotate("text", x = lower_bound, y = 0.5,
label = paste("Доод:", comma(lower_bound)), color = "blue", size = 3) +
annotate("text", x = upper_bound, y = 0.5,
label = paste("Дээд:", comma(upper_bound)), color = "blue", size = 3) +
labs(title = "KFC Mongolia: Outlier тодорхойлолт",
subtitle = "IQR Rule (Q1 - 1.5*IQR, Q3 + 1.5*IQR)",
x = "Үнэ (₮)", color = "Төрөл") +
scale_x_continuous(labels = comma_format()) +
theme_minimal() +
theme(axis.text.y = element_blank(), axis.title.y = element_blank())

9. Нэгтгэл (Summary)
summary_df <- data.frame(
Үзүүлэлт = c("Нийт бүтээгдэхүүн", "Нийт ангилал", "Нийт салбар",
"Хамгийн хямд", "Хамгийн үнэтэй",
"Дундаж үнэ", "Медиан үнэ"),
Утга = c(
nrow(menu),
n_distinct(menu$category_en),
nrow(branches),
paste(menu$name_en[which.min(menu$price)], "-", comma(min(menu$price)), "₮"),
paste(menu$name_en[which.max(menu$price)], "-", comma(max(menu$price)), "₮"),
paste(comma(round(mean(menu$price), 0)), "₮"),
paste(comma(round(median(menu$price), 0)), "₮")
)
)
knitr::kable(summary_df, caption = "KFC Mongolia Нэгтгэл")
KFC Mongolia Нэгтгэл
| Нийт бүтээгдэхүүн |
47 |
| Нийт ангилал |
7 |
| Нийт салбар |
28 |
| Хамгийн хямд |
PEPSI R1 - 1,000 ₮ |
| Хамгийн үнэтэй |
12PCS CHICKEN T - 50,500 ₮ |
| Дундаж үнэ |
8,328 ₮ |
| Медиан үнэ |
6,500 ₮ |