R:ggrepel,ggplot2 绘图区域上方的标签

Posted

技术标签:

【中文标题】R:ggrepel,ggplot2 绘图区域上方的标签【英文标题】:R: ggrepel, ggplot2 labels above the plotting area 【发布时间】:2022-01-18 21:02:19 【问题描述】:

In 想绘制具有特定值的密度图(例如:中值/平均值/等)。我还想在绘图区域上方显示选择的值(例如中位数),这样它就不会干扰分布本身。此外,在现实生活中,我有更大、更多样化的数据框(类别更多),所以我想分散标签,这样它们就不会相互干扰(我希望它们可读且视觉上令人愉悦)。

我在这里找到了类似的帖子:ggrepel labels outside (to the right) of ggplot area

我尝试采用这种策略(通过固定 x 坐标而不是 y 并扩大上边距),但无济于事。

这是 reprex 数据框:

set.seed(123)

group <- c(rep("control",367), rep("catalytic",276), rep("substrate",304))
sample_name <- c(rep("wt1",100), rep("wt2",75), rep("wt3",192), rep("cat1",221), rep("cat2",55), rep("sub1",84), rep("sub2",67), rep("sub3",153))
tail_length<- c(rnorm(100, mean=100, sd=3), rnorm(75, mean=98, sd=5),rnorm(192, mean=101, sd=2),rnorm(221, mean=88, sd=9),rnorm(55, mean=87, sd=6),rnorm(84, mean=182, sd=2),rnorm(67, mean=165, sd=9),rnorm(153, mean=153, sd=14))

tail_data <- data.frame(group, sample_name,tail_length)

这是我的绘图功能:

plot_distribution_with_values <- function(input_data,value_to_show="mean", grouping_factor = "group", title="", limit="") 
  
  #determine the center values to be plotted as x intercepting line(s)
  center_values = input_data %>% dplyr::group_by(!!rlang::sym(grouping_factor)) %>% dplyr::summarize(median_value = median(tail_length,na.rm = TRUE),mean_value=mean(tail_length,na.rm=T))
  
  #main core of the plot
  plot_distribution <- ggplot2::ggplot(input_data, aes_string(x=tail_length,color=grouping_factor)) + geom_density(size=1, aes(y=..ndensity..)) + theme_bw() + scale_x_continuous(limits=c(0, as.numeric(limit))) + coord_cartesian(ylim = c(0, 1))
  
  if (value_to_show=="median") 
    center_value="median_value"
  
  else if (value_to_show=="mean") 
    center_value="mean_value"
  
  
  #Plot settings (aesthetics, geoms, axes behavior etc.):
  g.line <- ggplot2::geom_vline(data=center_values,aes(xintercept=!!rlang::sym(center_value),color=!!rlang::sym(grouping_factor)),linetype="longdash",show.legend = FALSE) 
  g.labs <- ggplot2::labs(title= "Tail lengths distribution",
                          x="tail length [units]",
                          y= "normalized density",
                          color=grouping_factor)
  g.values <- ggrepel::geom_text_repel(data=center_values,aes(x=round(!!rlang::sym(center_value)),y=length(data),color=!!rlang::sym(grouping_factor),label=formatC(round(!!rlang::sym(center_value)),digits=1,format = "d")),size=4, direction = "x", segment.size = 0.4, show.legend =F, hjust =0, xlim = c(0,200), ylim = c(0, 1))

  
  #Overall plotting configuration:
  plot <- plot_distribution + g.line + g.labs + g.values
  

  return(plot)

这是示例函数调用:

plot_distribution_with_values(tail_data, value_to_show = "median", grouping_factor = "group", title = "Tail plot", limit=200)

下面是我得到的输出:

这是我想要的输出(对不起质量,在油漆中编辑):

另外,如果您更改“sample_name”的分组因子,那么您会看到更多“拥挤”的图,更类似于我的 irl 数据。

【问题讨论】:

【参考方案1】:

实现您想要的结果的一个选项:

    设置clip="off" in coord_cartesian` 通过增加标题的下边距为标签腾出一些空间 为标签设置y=1.05(数据范围的最大值+默认扩展0.05) 设置min.segment.length=0 增加标签的ylim 微调标签的位置

注意:要获得您想要的结果,您可能需要调整微调、ylim 和边距的值。

set.seed(123)

library(ggplot2)
library(ggrepel)
library(dplyr)

plot_distribution_with_values <- function(input_data,value_to_show="mean", grouping_factor = "group", title="", limit="") 
  
  #determine the center values to be plotted as x intercepting line(s)
  center_values = input_data %>% dplyr::group_by(!!rlang::sym(grouping_factor)) %>% dplyr::summarize(median_value = median(tail_length,na.rm = TRUE),mean_value=mean(tail_length,na.rm=T))
  
  #main core of the plot
  plot_distribution <- ggplot2::ggplot(input_data, aes_string(x=tail_length,color=grouping_factor)) + 
    geom_density(size=1, aes(y=..ndensity..)) + theme_bw() + scale_x_continuous(limits=c(0, as.numeric(limit))) + 
    coord_cartesian(clip = "off", ylim = c(0, 1))
  
  if (value_to_show=="median") 
    center_value="median_value"
  
  else if (value_to_show=="mean") 
    center_value="mean_value"
  
  
  #Plot settings (aesthetics, geoms, axes behavior etc.):
  g.line <- ggplot2::geom_vline(data=center_values,aes(xintercept=!!rlang::sym(center_value),
                                                       color=!!rlang::sym(grouping_factor)),
                                linetype="longdash",show.legend = FALSE) 
  g.labs <- ggplot2::labs(title= "Tail lengths distribution",
                          x="tail length [units]",
                          y= "normalized density",
                          color=grouping_factor)
  g.values <- ggrepel::geom_text_repel(data=center_values, 
                                       aes(x=round(!!rlang::sym(center_value)),
                                           y = 1.05, color=!!rlang::sym(grouping_factor),
                                           label=formatC(round(!!rlang::sym(center_value)),digits=1,format = "d")),
                                       size=4, direction = "x", segment.size = 0.4,
                                       min.segment.length = 0, nudge_y = .15, nudge_x = -10,
                                       show.legend =F, hjust =0, xlim = c(0,200), 
                                       ylim = c(0, 1.15))
  
  
  #Overall plotting configuration:
  plot <- plot_distribution + g.line + g.labs + g.values + 
    theme(plot.title = element_text(margin = margin(b = 4 * 5.5)))
  
  
  return(plot)


plot_distribution_with_values(tail_data, value_to_show = "median", grouping_factor = "group", title = "Tail plot", limit=200)

【讨论】:

太棒了!谢谢!使用这个和调整边距和轻推,我制作了一组我在视觉上非常喜欢的情节。

以上是关于R:ggrepel,ggplot2 绘图区域上方的标签的主要内容,如果未能解决你的问题,请参考以下文章

R语言ggplot2可视化:使用ggrepel包在线图(line plot)的尾端那个数据点添加数值标签(number label)

R语言ggplot2可视化:使用ggrepel包在线图(line plot)的尾端那个数据点添加文本标签(text label)

R语言ggplot2可视化自定义图例的位置实战:legend position相对于绘图区域配置自定义图例位置

【R】ggplot2绘图技巧

获取绘图区域ggplot2的笛卡尔坐标

裁剪出情节周围的 ggplot2 空白