使用R语言编写一个生成金字塔图形的函数

如何使用R语言编写一个生成金字塔图形的函数,如下图

主要思想分成2步,1是先生成金字塔5个方框的的数据参数,2是绘图

先生成一些关键参数

l

r 复制代码
evels  = c("L1","L2","L3","L4","L5"),
    palette = c("#8e24aa","#3f51b5","#2196f3","#4caf50","#fbc02d")
) {
  
  tiers <- 5
  H  <- tiers * 1.0   
  BW <- 3.4            
  
  w_at <- function(y) (BW/2) * (1 - y / H)
  y_breaks <- seq(0, H, length.out = tiers + 1)

构建多边形(金字塔各层)

r 复制代码
poly_list <- lapply(seq_len(tiers), function(i) {
    ymin <- y_breaks[i]
    ymax <- y_breaks[i + 1]
    wt   <- w_at(ymax)
    wb   <- w_at(ymin)
    data.frame(
      tier = i,
      x = c(-wt, wt, wb, -wb),
      y = c(ymax, ymax, ymin, ymin)
    )
  })
  poly_df <- do.call(rbind, poly_list)

标签位置数据框

r 复制代码
lab_df <- data.frame(
    tier  = seq_len(tiers),
    ymin  = y_breaks[-(tiers + 1)],
    ymax  = y_breaks[-1]
  )
  
  lab_df $ y_mid <- (lab_df $ ymin + lab_df $ ymax) / 2
  lab_df $ w_mid <- w_at(lab_df $ y_mid)
  lab_df $ label <- rev(levels)                
  lab_df $ fill  <- palette
  
  # 
  lab_df $ label_x <- 0
  
  # 自动换行
  wrap_width <- 25
  wrap_fun <- function(s, w) paste(strwrap(s, width = w), collapse = "\n")
  lab_df $ label_wrapped <- vapply(lab_df $ label, wrap_fun, character(1), w = wrap_width)
  
  # 合并填充色到多边形数据
  poly_df <- merge(poly_df, transform(lab_df, tier = tier, fill = fill), by = "tier", sort = FALSE)

最终得到如下绘图数据,可以加强你对ggplot2的绘图理解

有了绘图数据就可以绘图了,咱们把上面步骤打包成一个函数

r 复制代码
library(ggplot2)

ggpyramid <- function(
    levels  = c("L1","L2","L3","L4","L5"),
    palette = c("#8e24aa","#3f51b5","#2196f3","#4caf50","#fbc02d")
) {
  
  tiers <- 5
  H  <- tiers * 1.0   
  BW <- 3.4            
  
  w_at <- function(y) (BW/2) * (1 - y / H)
  y_breaks <- seq(0, H, length.out = tiers + 1)
  
  # 构建多边形(金字塔各层)
  poly_list <- lapply(seq_len(tiers), function(i) {
    ymin <- y_breaks[i]
    ymax <- y_breaks[i + 1]
    wt   <- w_at(ymax)
    wb   <- w_at(ymin)
    data.frame(
      tier = i,
      x = c(-wt, wt, wb, -wb),
      y = c(ymax, ymax, ymin, ymin)
    )
  })
  poly_df <- do.call(rbind, poly_list)
  
  # 标签位置数据框
  lab_df <- data.frame(
    tier  = seq_len(tiers),
    ymin  = y_breaks[-(tiers + 1)],
    ymax  = y_breaks[-1]
  )
  
  lab_df $ y_mid <- (lab_df $ ymin + lab_df $ ymax) / 2
  lab_df $ w_mid <- w_at(lab_df $ y_mid)
  lab_df $ label <- rev(levels)                
  lab_df $ fill  <- palette
  
  # 
  lab_df $ label_x <- 0
  
  # 自动换行
  wrap_width <- 25
  wrap_fun <- function(s, w) paste(strwrap(s, width = w), collapse = "\n")
  lab_df $ label_wrapped <- vapply(lab_df $ label, wrap_fun, character(1), w = wrap_width)
  
  # 合并填充色到多边形数据
  poly_df <- merge(poly_df, transform(lab_df, tier = tier, fill = fill), by = "tier", sort = FALSE)
  
  # 辅助函数:添加透明度
  add_alpha <- function(col, alpha) {
    rgb <- grDevices::col2rgb(col, TRUE) / 255
    grDevices::rgb(rgb[1], rgb[2], rgb[3], alpha = alpha)
  }
  
  # 绘图
  p <- ggplot() +
    geom_polygon(
      data = poly_df,
      aes(x = x, y = y, group = tier, fill = I(fill)),
      color = "white", linewidth = 1
    ) +
    geom_label(
      data = lab_df,
      aes(x = label_x, y = y_mid, label = label_wrapped),
      hjust = 0.5,        # 中对齐
      vjust = 0.5,
      label.size = 0,
      fill = add_alpha("white", 0.22),
      label.padding = unit(6, "pt"),
      size = 5,
      lineheight = 1.05,
      color = "black"
    ) +
    coord_equal(
      xlim = c(-BW/2 - 0.2, BW/2 + 0.5),
      ylim = c(0, H),
      expand = FALSE
    ) +
    labs(
      title    = "公众号:零基础说科研",
      subtitle = "天桥下的卖艺者",
      x = NULL, y = NULL
    ) +
    theme_void(base_size = 13) +
    theme(
      plot.title    = element_text(face = "bold", size = 18, hjust = 0.5),
      plot.subtitle = element_text(margin = margin(t = 4, b = 10), hjust = 0.5),
      panel.background = element_rect(fill = "#e6f7ff", color = NA),
      plot.background  = element_rect(colour = "gray", fill = NA),
      plot.margin = margin(20, 20, 20, 20)
    )
  
  p
}

绘图

r 复制代码
ggpyramid(
  levels = c("1", "2", "3", "4", "5"),
  palette = c("mediumpurple", "yellowgreen", "yellow", "gold", "red")
)

这样一个金字塔图形就绘制好了,还可以对很多参数调整,这个有什么用,其实没什么用,但是绘制图形能增强你对ggplot2的绘图原理的理解。

本期结束了,有点简单,主要是最近太忙了,目前正在编写竞争风险模型的加权算法的函数,支持各种加权包括nhanes,相信很快就可以和大家见面了

相关推荐
xiezhr2 小时前
逛GitHub发现了一款免费的带AI功能的数据库管理工具
数据库·ai编程·dba
吃糖的小孩1 天前
给 QQ AI 机器人设计“可控记忆”:会话摘要、手动长期记忆与角色卡边界
数据库
笃行3502 天前
金仓数据库数据安全双防线:静态存储加密与传输加密实战
数据库
笃行3502 天前
金仓数据库物理备份实战:sys_rman 全流程演练与误覆盖抢救
数据库
笃行3502 天前
金仓数据库逻辑备份实战:从全库导出到 Schema 替换的完整闭环
数据库
SelectDB3 天前
阶跃星辰基于 SelectDB 构建 PB 级 Agent 可观测平台
大数据·数据库·aigc
这个DBA有点耶3 天前
GROUP BY优化全解:如何写出既不丢数据又飞快的分组查询
数据库·mysql·架构
掉头发的王富贵3 天前
【StarRocks】极限十分钟入门StarRocks
数据库·sql·mysql
Nturmoils3 天前
WHERE 条件别凭习惯写,常用查询先跑一遍
数据库