是否有一种编程方式可以在 ggplot2 图上传递 y 轴的特定范围?
Is there a programatic way to pass specific ranges for the y-axis on a ggplot2 plot?
我有根据一些用户输入自动生成的图。大多数时候,情节都很好。但是,一些用户要求确保绘制数据的每一端始终有一个轴标签。例如,这个情节:
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"
)
在最高点以上或最低点以下没有标签。我可以使用 expand_limits
:
轻松添加它们
ggplot(
sample_data
, aes(x = x, y = y)) +
stat_summary(
fun = "mean"
) +
expand_limits(y = c(2, 10))
但是,因为这些图是自动生成的,我不能每次都手动添加下一个轴点。我已经尝试将 only.loose = TRUE
传递给 labeling:extended
,但这仍然不会改变显示的值(除了输入我想要的值之外):
ggplot(
sample_data
, aes(x = x, y = y)) +
stat_summary(
fun = "mean"
) +
scale_y_continuous(breaks = breaks_extended(only.loose = TRUE))
此外,有些图比这更复杂(例如,有或没有置信区间、额外分组等),数据是使用 dplyr
为图准备的,并直接通过管道传输进入 ggplot
(%>%
)。因此,即使是重新计算值之类的事情也很重要。
事实上,即使在这种情况下,它也会失败,因为添加扩展点以捕获下一组标签会更改标签。
ggplot(
sample_data
, aes(x = x, 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)}
)
看来这是因为
labeling::extended(2.5, 8.5, 5, only.loose = TRUE)
returns 范围 2 到 9 以 1 为单位,而:
labeling::extended(2, 9, 5, only.loose = TRUE)
returns 范围 2 到 10 以 2 为单位。不知何故,breaks_extended
增加了一些变化,尽管我是否追踪它并没有太大变化。我可以通过先计算中断来解决这个问题,但是(再次)这是针对一组相当复杂的图。
我觉得我遗漏了一些明显的要点,但它一直在躲避我。
是的,有一种编程方式可以设置 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-03-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,
aes(x = x, y = y)) +
stat_summary(
fun = "mean"
) +
scale_y_continuous(
limits = my_lims_expand
, breaks = pretty
)
生成所需的图:
我有根据一些用户输入自动生成的图。大多数时候,情节都很好。但是,一些用户要求确保绘制数据的每一端始终有一个轴标签。例如,这个情节:
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"
)
在最高点以上或最低点以下没有标签。我可以使用 expand_limits
:
ggplot(
sample_data
, aes(x = x, y = y)) +
stat_summary(
fun = "mean"
) +
expand_limits(y = c(2, 10))
但是,因为这些图是自动生成的,我不能每次都手动添加下一个轴点。我已经尝试将 only.loose = TRUE
传递给 labeling:extended
,但这仍然不会改变显示的值(除了输入我想要的值之外):
ggplot(
sample_data
, aes(x = x, y = y)) +
stat_summary(
fun = "mean"
) +
scale_y_continuous(breaks = breaks_extended(only.loose = TRUE))
此外,有些图比这更复杂(例如,有或没有置信区间、额外分组等),数据是使用 dplyr
为图准备的,并直接通过管道传输进入 ggplot
(%>%
)。因此,即使是重新计算值之类的事情也很重要。
事实上,即使在这种情况下,它也会失败,因为添加扩展点以捕获下一组标签会更改标签。
ggplot(
sample_data
, aes(x = x, 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)}
)
看来这是因为
labeling::extended(2.5, 8.5, 5, only.loose = TRUE)
returns 范围 2 到 9 以 1 为单位,而:
labeling::extended(2, 9, 5, only.loose = TRUE)
returns 范围 2 到 10 以 2 为单位。不知何故,breaks_extended
增加了一些变化,尽管我是否追踪它并没有太大变化。我可以通过先计算中断来解决这个问题,但是(再次)这是针对一组相当复杂的图。
我觉得我遗漏了一些明显的要点,但它一直在躲避我。
是的,有一种编程方式可以设置 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-03-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,
aes(x = x, y = y)) +
stat_summary(
fun = "mean"
) +
scale_y_continuous(
limits = my_lims_expand
, breaks = pretty
)
生成所需的图: