微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否有一种编程方式可以在 ggplot2 图中传递 y 轴的特定范围?

如何解决是否有一种编程方式可以在 ggplot2 图中传递 y 轴的特定范围?

我有一些根据用户输入自动生成的图。大多数情况下,这些情节工作正常。然而,一些用户要求确保在绘制数据的每一端总是有一个标签。例如,这个情节:

sample_data <-
  data.frame(
    x = rep(LETTERS[1:3],each = 3),y = 1:9 + 0.5
  )


ggplot(
  sample_data,aes(x = x,y = y)) +
  stat_summary(
    fun = "mean"
  )

enter image description here

在顶点上方或底点下方没有标签。我可以使用 expand_limits 轻松添加它们:

ggplot(
  sample_data,y = y)) +
  stat_summary(
    fun = "mean"
  ) +
  expand_limits(y = c(2,10))

enter image description here

但是,因为这些图是自动生成的,我不能每次都手动添加一个轴点。我试过将 only.loose = TRUE 传递给 labeling:extended,但这仍然没有改变显示的值(只是输入我想要的值):

ggplot(
  sample_data,y = y)) +
  stat_summary(
    fun = "mean"
  ) +
  scale_y_continuous(breaks = breaks_extended(only.loose = TRUE))

enter image description here

此外,一些图比这更复杂(例如,有或没有置信区间、附加分组等),数据是使用 dplyr 为图准备的,并直接输入 { {1}}(带有 ggplot)。因此,即使是像重新计算值这样的事情也不是微不足道的。

事实上,即使在这种情况下,它也会失败,因为添加扩展点以捕获下一组标签会更改标签

%>%

enter image description here

这似乎是因为

ggplot(
  sample_data,y = y)) +
  stat_summary(
    fun = "mean"
  ) +
  scale_y_continuous(breaks = breaks_extended(n = 5,only.loose = TRUE)) +
  expand_limits(y =
                  sample_data %>%
                  group_by(x) %>%
                  summarise(my_mean = mean(y)) %>%
                  pull(my_mean) %>%
                  range() %>%
                  {labeling::extended(.[1],.[2],5,only.loose = TRUE)}
                  )

用 1 返回 2 到 9 的范围,同时:

labeling::extended(2.5,8.5,only.loose = TRUE)

以 2 为单位返回 2 到 10 的范围。不知何故,labeling::extended(2,9,only.loose = TRUE) 增加了一些变化,尽管我是否追踪它并没有太大变化。我可以通过先计算间隔来解决这个问题,但(再次)这是一组相当复杂的图。

我觉得我遗漏了一些明显的点,但它一直在躲避我。

解决方法

是的,有一种编程方式来设置 y 尺度的限制,即为 limits 参数提供一个函数。将自然数据限制作为输入,然后您可以以编程方式对其进行编辑。休息也是如此,除了输入是限制。

下面的示例,此代码的确切外观取决于您的规范。

library(ggplot2)

sample_data <- data.frame(
  x = rep(LETTERS[1:3],each = 3),y = 1:9 + 0.5
)


ggplot(sample_data,aes(x = x,y = y)) +
  stat_summary(
    fun = "mean"
  ) +
  scale_y_continuous(
    limits = function(x) {
      lower <- floor(x[1])
      lower <- ifelse(x[1] - lower < 0.5,lower - 1,lower)
      upper <- ceiling(x[2])
      upper <- ifelse(upper - x[2] <= 0.5,upper + 1,upper)
      c(lower,upper)
    },breaks = function(x) {
      scales::breaks_pretty()(x)
    }
  )
#> Warning: Removed 3 rows containing missing values (geom_segment).

reprex package (v1.0.0) 于 2021 年 3 月 23 日创建

,

受 teunbrand 的启发,我构建了一个生成限制的函数,然后检查以确保扩展(包括 5% 的缓冲区)不会改变 pretty 的输出

my_lims_expand <- function(x){
  prev_pass <-
    range(pretty(x))
  
  curr_pass <-
    pretty(c(prev_pass[1] - 0.05 * diff(prev_pass),prev_pass[2] + 0.05 * diff(prev_pass)))
  
  last_under <-
    tail(which(curr_pass < min(x)),1)
  
  first_over <-
    head(which(curr_pass > max(x)),1)
  
  out <-
    range(curr_pass[last_under:first_over])
  
  confirm_out <-
    range(pretty(out))
  
  while(!all(out == confirm_out)){
    prev_pass <- curr_pass
    
    curr_pass <-
      pretty(c(prev_pass[1] - 0.05 * diff(prev_pass),prev_pass[2] + 0.05 * diff(prev_pass)))
    
    last_under <-
      tail(which(curr_pass < min(x)),1)
    
    first_over <-
      head(which(curr_pass > max(x)),1)
    
    out <-
      range(curr_pass[last_under:first_over])
    
    confirm_out <-
      range(pretty(out))
  }
  
  
  return(out)
}

然后,我可以将该函数用于 limits

ggplot(sample_data,y = y)) +
  stat_summary(
    fun = "mean"
  ) +
  scale_y_continuous(
    limits = my_lims_expand,breaks = pretty
  )

生成所需的图:

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?