数据可视化期末报告

Author

221527136邹伟亮

1 报告要求

  • 期末实验报告由5章节5个图形组成,每个章节需要作一个图形。

  • 每个章节选择作什么图自主选择,作图前补充完整图形标题名称,例如:图形1——多变量条形图。

  • 案例数据自主收集,不同章节可以公用一个数据集。但同学间不允许使用相同数据集。

  • 每个章节的数据集合需要通过datatable 函数展示,并简要解释数据来源和变量意义。

  • 每个输出图形后需要对图形作简要解读,最少需针对图形提出一个观点。

  • 渲染html文件保留代码展示,6月22日前将发布网址提交至共享文档“8、期末报告” 列中。

  • 评分标准:

    • 每章节图形各20分

    • 能有效输出图形和合理解释75%

    • 数据独特性强10%

    • 图形个性化强15%

2 类别数据可视化

2.1 案例数据解释与展示

2.1.0.1 数据来源与变量解释

  • 数据来源:大众点评网餐厅口碑数据,包含广州粤菜餐厅的详细信息,如行政区、评论数、评分和人均消费等。因原始数据过多仅展示选取后用于绘图的数据。

  • 变量说明

    • Type:菜系类型(如粤菜、川菜等)

    • District:餐厅所在行政区(如天河区、越秀区等)

    • FlavorScore:口味评分(0-10 分)

    • EnvironmentScore:环境评分(0-10 分)

    • ServiceScore:服务评分(0-10 分)

library(dplyr)
library(DT)  # 用于交互式表格展示
library(ggplot2)  # 用于绘图
library(readxl)             # 加载包
library(xts)
# 读取数据并计算平均评分
plot_data <- read.csv("大众点评网餐厅口碑数据.csv", fileEncoding = "GB18030") %>%
  select(Type, District, FlavorScore, EnvironmentScore, ServiceScore) %>%
  group_by(Type, District) %>%
  summarise(
    across(c(FlavorScore, EnvironmentScore, ServiceScore), ~ mean(.x, na.rm = TRUE)),
    .groups = "drop"
  )
# 使用 DT 包展示数据
datatable(plot_data,rownames = FALSE)

2.2 图形1——可互动多变量条形图

library(dplyr)
library(tidyr)
library(ggplot2)
library(plotly)

# 数据处理
plot_data_long <- plot_data %>%
  group_by(Type, District) %>%
  summarise(
    across(c(FlavorScore, EnvironmentScore, ServiceScore), 
           ~mean(., na.rm = TRUE)),
    OverallScore = (FlavorScore + EnvironmentScore + ServiceScore)/3,
    .groups = "drop"
  ) %>%
  arrange(District, desc(OverallScore)) %>%
  mutate(Type = factor(Type, levels = unique(Type))) %>%
  pivot_longer(
    cols = ends_with("Score") & !OverallScore,
    names_to = "Metric",
    values_to = "Score"
  ) %>%
  mutate(Metric = case_when(
    Metric == "FlavorScore" ~ "口味评分",
    Metric == "EnvironmentScore" ~ "环境评分",
    Metric == "ServiceScore" ~ "服务评分",
    TRUE ~ Metric
  )) %>%
  filter(District %in% {
    district_rank <- . %>%
      group_by(District) %>%
      summarise(MeanScore = mean(Score, na.rm = TRUE)) %>%
      arrange(desc(MeanScore)) %>%
      slice_head(n = 6) %>%
      pull(District)
    district_rank(.)
  })

# 绘制分面图
p <- ggplot(
  plot_data_long,
  aes(
    x = Type,
    y = Score,
    fill = Metric,
    text = paste(
      "菜系:", Type, "\n",
      "行政区:", District, "\n",
      "指标:", Metric, "\n",
      "评分:", round(Score, 1)
    )
  )
) +  
  geom_col(width = 0.7,                 # 设置条形宽度
           position = position_dodge(width = 0.8),  # 绘制并列条形图
           color = "gray50") +          # 为条形图添加灰色边框
  geom_text(aes(label = round(Score, 1)),  # 添加数据标签
           position = position_dodge(0.8),
           size = 2.5,                   # 设置标签字体大小
           color = "black",              # 设置标签颜色
           vjust = -0.5) +              # 垂直位置调整
  facet_wrap(~ District, ncol = 2) +
  scale_fill_manual(
    values = c("#66C2A5", "#FC8D62", "#8DA0CB"),  # 自定义颜色
    name = "评分指标"  # 图例标题
  ) +
  scale_y_continuous(limits = c(0, 1.1 * max(plot_data_long$Score))) +  # 设置y轴范围
  labs(
    title = "广州各菜系评分对比(TOP6行政区)",
    x = NULL,
    y = "平均评分"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
    strip.text = element_text(face = "bold"),
    legend.position = "top",
    plot.title = element_text(hjust = 0.5, face = "bold")
  )

# 交互式优化
ggplotly(p, tooltip = "text") %>%
  layout(
    hoverlabel = list(
      bgcolor = "white",
      font = list(size = 12, family = "Microsoft YaHei")
    ),
    margin = list(l = 50, r = 50, b = 80, t = 80),
    font = list(family = "Microsoft YaHei")
  )
  • 图形解读:

  • 1. 区域餐饮品质梯度明显

    • 第一梯队(天河区、海珠区、萝岗区):综合评分均超过7.8分,其中萝岗区环境评分表现尤为突出(均值8.4分),但服务评分普遍低于环境分0.3-0.5分,显示硬件设施优势与服务软实力不匹配。

    • 第二梯队(番禺区、白云区、增城区):综合评分7.5-7.7分,服务评分成为主要短板(如白云区川菜服务分7.6 vs 环境分7.7),需优先改进服务流程。

    2.2.0.1 2. 菜系表现两极分化

    • 高端菜系:在核心行政区(天河、萝岗)环境与服务评分均超8分,但外围区域(如增城)评分骤降0.8分,反映高端餐饮对区位依赖性极强。

    • 平价菜系:所有行政区评分均低于7.5分,且环境评分最低(白云区仅7.2分),需提升用餐环境基础配置。

3 数据分布可视化

3.1 案例数据解释与展示

  • 数据来源:大众点评网餐厅口碑数据,包含广州粤菜餐厅的详细信息,如行政区、评论数、评分和人均消费等。其中只选取数据量大于200的行政区。
  • 变量意义

    • PerConsumption:数值变量,表示餐厅人均消费金额(单位:元),反映定价水平和市场定位。

    • District:分类变量,表示行政区,用作分面变量,筛选出6个数据量>200的区域。

# 加载数据
df <- read.csv("大众点评网餐厅口碑数据.csv", stringsAsFactors = FALSE,fileEncoding = "GB18030")

# 数据预处理
df2 <- df |> 
  select(District, PerConsumption, ReviewNum, Level, Type) |> 
  filter(!is.na(PerConsumption), !is.na(ReviewNum), !is.na(Level)) |> 
  group_by(District) |> 
  filter(n() > 200) |> #选取大于200数据量的行政区
  ungroup()


datatable(df2,rownames = FALSE)

3.2 图形2——小提琴图

# 加载所需包
library(tidyr)
library(ggplot2)
library(dplyr)
library(forcats)


# 数据预处理
df <- df |> 
  select(District, PerConsumption) |> 
  filter(!is.na(PerConsumption)) |>  # 移除NA值
  mutate(District = fct_inorder(District))  # 转为有序因子

# 限制价格范围以避免极端值
df2$PerConsumption[df2$PerConsumption >500] <- 500

# 绘制分组小提琴图
ggplot(df2, aes(x = District, y = PerConsumption, fill = District)) +
  geom_violin(scale = "width", trim = FALSE, alpha = 0.6) +  # trim=FALSE保留尾部
  geom_boxplot(width = 0.1, fill = "white", outlier.shape = NA) +  # 添加箱线图
  scale_fill_brewer(palette = "Blues") +  # 使用蓝色调色板
  labs(title = "广州不同行政区餐厅人均消费分布",
       x = "行政区",
       y = "人均消费(元)") +
  theme_minimal() +
  theme(legend.position = "none",  # 移除图例,x轴已显示类别
        axis.text.x = element_text(angle = 45, hjust = 1)) +  # 旋转x轴标签
  coord_flip()  # 旋转坐标轴,便于阅读

  • 图形解读:
    • 图形描述:分组小提琴图展示了12个行政区餐厅人均消费的分布。小提琴宽度反映消费密度的分布,内部箱线图显示中位数和四分位距。coord_flip()使行政区标签更易阅读。

    • 分布特征: 样本量大的行政区(如天河区910个、越秀区653个)的小提琴图较宽,分布右偏(底部宽,顶部细),表明大多数消费集中在较低值(例如100-300元),少数高端餐厅拉高尾部。

    • 观点:天河区和越秀区的消费分布较宽且中位数较高,表明这些区域的餐饮市场多样化,涵盖了从大众消费(100-200元)到高端消费(500元)的餐厅,这与它们作为广州商业和文化中心的地位相符。

4 变量关系可视化

4.1 案例数据解释与展示

  • 变量意义

  • 数据来源:大众点评网餐厅口碑数据,包含广州粤菜餐厅的详细信息,如行政区、评论数、评分和人均消费等。其中只选取数据量大于200的行政区。

    • PerConsumption:数值变量,表示餐厅人均消费金额(单位:元),用作x轴,反映定价水平。

    • ReviewNum:数值变量,表示评论总数,用作y轴,反映受欢迎程度。

    • Type:分类变量,表示菜品种类,用作分面变量。

    • District:分类变量,表示行政区,用作分面变量,筛选出6个数据量>200的区域。

# 加载数据
df <- read.csv("大众点评网餐厅口碑数据.csv", stringsAsFactors = FALSE,fileEncoding = "GB18030")
# 数据预处理
df3 <- df |> 
  select(District, PerConsumption, ReviewNum, Type) |> 
  filter(!is.na(PerConsumption), !is.na(ReviewNum)) |> 
  group_by(District) |> 
  filter(n() > 200) |> #选取大于200数据量的行政区
  ungroup()


datatable(df3,rownames = FALSE)

4.2 图形3——分面散点图

# 加载所需包
library(ggplot2)
library(dplyr)
library(forcats)
library(gridExtra)

# 限制评论数范围以避免极端值
df3$ReviewNum[df3$ReviewNum > 8000] <- 8000
# 限制价格范围以避免极端值
df3$PerConsumption[df3$PerConsumption > 300] <- 300

# 绘制分面散点图
ggplot(data = df3, aes(x = PerConsumption, y = ReviewNum, color = District)) +
  geom_point(size = 1.5, na.rm = TRUE) +
  stat_smooth(method = "lm", color = "red", fill = "deepskyblue", size = 0.7, na.rm = TRUE) +
  labs(title = "广州不同行政区餐厅人均消费与评论数分布",
       x = "人均消费(元)",
       y = "评论数") +
  theme(
    legend.position = "none",
    panel.spacing.x = unit(0.2, "lines"),
    panel.spacing.y = unit(0.2, "lines"),
    axis.text.x = element_text(angle = 45, hjust = 1)
  ) +
facet_grid(District ~ Type, scales = "fixed") +
scale_x_continuous(breaks = seq(0, 500, by = 100))

  • 图形解读:
  • 粤菜餐厅分布特征
    • 天河区和越秀区的粤菜餐厅呈现明显的”高消费-高评论”聚集现象,表明这两个区域的高端粤菜餐厅更受消费者关注和评价
  • 价格与关注度的正相关
    • 在川菜类别中,几乎所有行政区都显示出人均消费与评论数呈正相关趋势(红色趋势线向上倾斜)
  • 粥粉面类别的特殊性
    • 粥粉面作为平民餐饮,在各区都集中在低消费区间(人均<50元)

    • 评论数分布相对均匀,没有明显随价格增长的趋势,说明这类基础餐饮的关注度与价格关联不大

  • 观点:高端餐饮(特别是日料和西餐)本身就具有较高消费者评价和社交分享,川菜的价格提升可能带来更多的消费者评价和社交分享,而大众餐饮如粥粉面的评价行为则与价格无关。天河区作为广州商业中心,其高端餐饮获得了不成比例的高关注度。

5 样本相似性可视化

5.1 案例数据解释与展示

  • 数据来源:大众点评网餐厅口碑数据,包含广州粤菜餐厅的详细信息,如行政区、评论数、评分和人均消费等。其中只选取数据量大于200的行政区。

    • PerConsumption:数值变量,表示餐厅人均消费金额(单位:元),用作x轴,反映定价水平。

    • Type:分类变量,表示菜品种类,用作分面变量。

    • District:分类变量,表示行政区,用作分面变量,筛选出6个数据量>200的区域。

# 加载数据
df <- read.csv("大众点评网餐厅口碑数据.csv", stringsAsFactors = FALSE,fileEncoding = "GB18030")
# 数据预处理
df4 <- df |> 
  select(District, PerConsumption, Type) |> 
  filter(!is.na(PerConsumption)) |> 
  group_by(District) |> 
  filter(n() > 200) |> #选取大于200数据量的行政区
  ungroup()


datatable(df4,rownames = FALSE)

5.2 图形4——热图

library(pheatmap)

# 创建矩阵 - 各区不同类型餐厅的人均消费
mat <- with(df4, tapply(PerConsumption, list(District, Type), mean, na.rm=TRUE))

# 绘制热图
pheatmap(mat,
         color = colorRampPalette(c("navy","white","firebrick3"))(100),
         display_numbers=TRUE,
         cellheight_row=6,
         fontsize=12,
         angle_col=0,
         treeheight_row=50,
         treeheight_col=35,
         cluster_col=FALSE,
         cutree_row=3)

  • 图形解读:
  • 日式料理价格区间最广且最高端
    • 日式料理的最高消费达到129.98元,是所有菜系中最高的

    • 但同时也有68.24元的中等价位,价格跨度达61.74元

    • 这表明日式料理在不同餐厅可能有完全不同的定位(高端日料vs平价日料)

  • 消费层次结构明显
    • 价格排序:日式料理(129.98) > 粤菜(114.59) > 西餐(103.63) > 川菜(70.19) > 粥粉面(26.72)

    • 符合大众对这几类餐饮的价格认知,日料和粤菜定位较高端,粥粉面最平价

  • 观点:高端餐饮(日料/西餐)的天然社交溢价,数据中日式料理(最高129.98元)和西餐(103.63元)价格显著高于其他品类,其消费场景往往伴随社交分享需求(如打卡、仪式感)。高价本身可能通过”凡勃伦效应”(Veblen Effect)刺激消费者更主动评价和传播,形成正向循环。

6 时间序列可视化

6.1 案例数据解释与展示

  • 数据来源:中国宏观经济数据库-月度(主要城市),统计了2011年1月至2025年4月各城市二手住宅销售价格指数(上年同月=100)。

  • 变量意义

    • 北京/上海/深圳等列:价格指数,数值表示当年某月价格与上年同月的百分比变化

    • 时间:显示2011-2025年月份时间

#读取数据
df5.0 <- read_xlsx("中国宏观经济数据库-月度(主要城市).xlsx", skip = 1)
# 转换时间格式,"%m-%Y" -> 日期格式,默认为该月1号
df5 <- df5.0 %>%
  mutate(时间 = as.Date(paste0("01-", 时间), format = "%d-%m-%Y")) %>%
  arrange(时间)
# 转xts时间序列对象,只选北京 上海 深圳列
dts <- xts(df5 %>% select(北京, 上海, 深圳), order.by = df5$时间)

datatable(df5.0,rownames = FALSE)

6.2 图形5——时间序列动态交互图

library(readxl)
library(lubridate)
library(dplyr)
library(dygraphs)
library(xts)
dygraph(data=dts[,c(1,2,3)],xlab="时间",ylab="价格指数(上年同月=100)",main="2011-2025年主要城市二手住宅销售价格指数动态交互图")%>%
  dyAxis("y", label = "价格指数(上年同月=100)", valueRange = c(80, 165)) %>%
  dyOptions(drawPoints = FALSE, pointSize = 2)%>%  # 不显示数据点,点大小为2
  dyRangeSelector(height = 30)  # 添加时间滑动条
  • 图形解读:
  • 核心趋势
    • 深圳波动最大:2015-2016年快速上涨(最高达160),2017年后显著回落,反映政策调控(如限购)的影响。

    • 北京与上海趋同:两者长期走势相似,但北京在2016-2017年跌幅更深,可能与首都政策敏感性更高有关。

  • 关键发现
    • 2020年拐点:三城市指数在2020年初短暂下跌(疫情冲击),但下半年迅速反弹,深圳反弹力度最强(政策宽松+需求释放)。