You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用base R或ggplot2制作含水平数据条的交叉分类数据表格?

实现单元格内嵌水平条形图的表格(ggplot2/base R方案)

针对你提到的formattable依赖phantomjs导致保存、输出像素化的问题,这里提供两个纯R原生/ggplot2的解决方案,完全避免额外依赖,且输出高清可自定义。

ggplot2方案(推荐,灵活性高)

用分面功能模拟表格结构,每个分面单元格绘制水平条形图,代码示例如下:

library(ggplot2)

# 构造模拟数据(替换成你的真实数据)
set.seed(123)
df <- expand.grid(
  Group = c("对照组", "实验组1", "实验组2"),  # 行分类变量
  Category = c("指标1", "指标2", "指标3", "指标4")  # 列分类变量
)
df$Value <- sample(20:95, nrow(df), replace = TRUE)  # 连续数值

# 绘制带内嵌条形图的表格
ggplot(df, aes(x = Value, y = 1)) +
  geom_col(fill = "#2E86AB", alpha = 0.8, width = 0.6) +  # 水平条形
  geom_text(aes(label = paste0(Value, "%")), hjust = -0.1, size = 3.8, color = "#333333") +  # 数值标签
  facet_grid(Group ~ Category, switch = "y") +  # 按行/列分类分面
  theme_minimal(base_size = 10) +
  theme(
    # 隐藏冗余坐标轴
    axis.title = element_blank(),
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.text.x = element_blank(),
    axis.ticks.x = element_blank(),
    # 调整表格样式
    panel.grid = element_blank(),
    strip.text.y.left = element_text(angle = 0, face = "bold", color = "#222222"),  # 行标签
    strip.text.x = element_text(face = "bold", color = "#222222"),  # 列标签
    strip.background = element_rect(fill = "#F0F0F0", color = "#CCCCCC"),
    panel.border = element_rect(color = "#CCCCCC", fill = NA),
    panel.spacing = unit(0, "mm")  # 去掉单元格间隙
  ) +
  scale_x_continuous(expand = expansion(mult = c(0, 0.2))) +  # 给数值标签留空间
  scale_y_discrete(expand = c(0, 0))

自定义技巧

  • 调整条形颜色:修改geom_col的fill参数,支持hex色码或R内置色名
  • 数值标签:调整hjust控制位置(0在条形右侧,-0.1在条形外),修改size/color改变样式
  • 保存高清输出:用ggsave("table_plot.pdf", width = 10, height = 6, dpi = 300)保存为PDF(矢量图无像素化)或PNG

Base R方案(无额外依赖)

如果不想用ggplot2,可通过layout手动划分单元格绘制,适合轻量场景:

# 使用上面的df数据
row_cats <- unique(df$Group)
col_cats <- unique(df$Category)
n_rows <- length(row_cats)
n_cols <- length(col_cats)
max_val <- max(df$Value)

# 设置布局:顶部列标题+左侧行标题+单元格区域
layout(matrix(
  c(0, rep(2, n_cols), rep(1, n_rows), 3:(3 + n_rows*n_cols - 1)),
  nrow = n_rows + 1, ncol = n_cols + 1
), widths = c(3, rep(6, n_cols)), heights = c(2, rep(5, n_rows)))

# 绘制顶部列标题
par(mar = c(0, 0, 0, 0))
plot(0, 0, type = "n", axes = FALSE, xlab = "", ylab = "")
for (i in 1:n_cols) {
  text(i/n_cols, 0.5, col_cats[i], font = 2, cex = 1.1)
}

# 绘制左侧行标题
par(mar = c(0, 0, 0, 0))
plot(0, 0, type = "n", axes = FALSE, xlab = "", ylab = "")
for (i in 1:n_rows) {
  text(0.5, (n_rows - i + 1)/n_rows, row_cats[i], font = 2, cex = 1.1)
}

# 逐个绘制单元格的条形图
par(mar = c(0.5, 0.5, 0.5, 0.5))
for (r in 1:n_rows) {
  for (c in 1:n_cols) {
    current_val <- df$Value[df$Group == row_cats[r] & df$Category == col_cats[c]]
    # 初始化空画布
    plot(0, 0, xlim = c(0, max_val), ylim = c(0, 1), type = "n", axes = FALSE, xlab = "", ylab = "")
    # 绘制条形
    rect(0, 0.3, current_val, 0.7, col = "#2E86AB", border = "#AAAAAA")
    # 绘制数值标签
    text(current_val + max_val*0.03, 0.5, paste0(current_val, "%"), cex = 0.9)
    # 绘制单元格边框
    box()
  }
}

这个方案完全不需要任何第三方包,直接用base R绘图函数实现,缺点是样式自定义需要逐个调整参数,不如ggplot2便捷。


内容的提问来源于stack exchange,提问作者whv20

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 12:23:23