Home

PCA分析店铺综合排名

· xiebro

在美食推荐应用中,用户对店铺的评价通常有“环境”、“服务”和“味道”等多方面的评分。
那么,如何通过这些评分来计算出一个更能代表整体印象的“综合评分”?本次练习使用主成分分析(PCA)来实现店铺的综合排名。

数据集概览

food.csv

library(dplyr)
library(plotly)

dat <- 
  read.csv("data/food.csv") %>%
  filter(种类 == "咖啡厅")

# 结构概览
glimpse(dat)
## Rows: 717
## Columns: 5
## $ 店名     <chr> "YECLIP COFFEE 黄色回形针咖啡", "hellopets·猪咖狗咖", "格度猫…
## $ 种类     <chr> "咖啡厅", "咖啡厅", "咖啡厅", "咖啡厅", "咖啡厅", "咖啡厅", "…
## $ 环境评分 <dbl> 4.10, 4.50, 4.74, 4.11, 4.18, 4.14, 4.03, 4.94, 3.92, 4.38, 4…
## $ 服务评分 <dbl> 3.97, 4.17, 4.35, 4.75, 4.57, 4.12, 4.39, 4.60, 4.43, 4.95, 3…
## $ 口味评分 <dbl> 4.16, 4.86, 4.67, 4.92, 4.96, 4.57, 4.93, 4.80, 4.04, 4.04, 3…
# 分布概览
plot_ly(
  dat,
  x = ~环境评分,
  y = ~服务评分,
  z = ~口味评分,
  type = "scatter3d",
  mode = "markers",
  marker = list(size = 1)
)

PCA分析

# 标准化
dat_scaled <- 
  dat %>%
  select(环境评分, 服务评分, 口味评分) %>%
  scale()

# PCA分析
pca_result <- prcomp(dat_scaled, center = TRUE, scale. = TRUE)

summary(pca_result)
## Importance of components:
##                           PC1    PC2    PC3
## Standard deviation     1.2076 0.9049 0.8502
## Proportion of Variance 0.4861 0.2729 0.2409
## Cumulative Proportion  0.4861 0.7591 1.0000
# 店铺综合评分结果
pca_scores <- 
  pca_result$x %>% # 提取主成分得分
  as.data.frame() %>% 
  cbind(dat) %>% 
  mutate(综合评分 = round(PC1, 1))

# 店铺综合排名
pca_scores %>% 
  select(店名, contains("评分")) %>% 
  arrange(desc(综合评分)) %>% 
  mutate(综合排名 = 1:n()) %>% 
  head(10) %>% 
  knitr::kable()
店名 环境评分 服务评分 口味评分 综合评分 综合排名
果徕咖啡庄园 4.95 4.94 4.76 2.2 1
博物馆咖啡厅 4.80 4.96 4.80 2.1 2
羊驼来了Young for you 4.95 4.76 4.84 2.0 3
MOJOC CAFE 4.95 4.96 4.63 2.0 4
农夫和兔 cafe 4.88 4.65 4.98 2.0 5
luckin coffee瑞幸咖啡(第一城店) 4.66 4.99 4.84 2.0 6
EN SPACE ·恩空间 4.68 4.93 4.80 1.9 7
墨閑山房 4.85 4.62 4.94 1.9 8
Sunrise大安正街店 4.90 4.71 4.82 1.9 9
CK柴犬柯基狗咖·猪咖(春熙路IFS店) 4.77 4.96 4.68 1.9 10
# 可视化PCA结果
pca_scores %>% 
  ggplot(aes(x = PC1, y = PC2)) +
  geom_point(alpha = .5) +
  geom_vline(xintercept = 0) +
  geom_hline(yintercept = 0) +
  theme_minimal()
plot_ly(
  pca_scores,
  x = ~PC1,
  y = ~PC2,
  z = ~PC3,
  type = "scatter3d",
  mode = "markers",
  marker = list(size = 1)
)