ggplot:单个方面的限制轴 limits/breaks
ggplot: limit axis limits/breaks of individual facet
我经常制作条形图,并将条形图的值另外包含为注释 (geom_text)。通常,我更喜欢这些值右对齐(与将标签放在条形顶部相反)。在绘制多面条形图时,我将这些值放在每个组中的最大值(我之前计算过)加上一点额外的 space,我通过乘以 x 值(我不使用 nudge_x因为它的绝对值可能适合某些方面但不适合其他方面)。
这种方法让我烦恼的是注释下剩余的轴标签。请参见下图(轴标签 15、100 和 2.5)。我想将 x 轴标签限制为(接近于)每个方面的最大值,而不是一直延伸到注释。
我想知道是否有更好的方法可用。
(我知道我可以用 group_split 生成所需的图形,例如拼凑。我感兴趣的是是否有直接的方法来限制每个单独面的轴 limits/labels) .
非常感谢。
library(tidyverse)
#> Warning: package 'dplyr' was built under R version 3.6.2
#> Warning: package 'forcats' was built under R version 3.6.3
mtcars %>%
group_by(cyl, gear) %>%
summarise(n_obs=n()) %>%
mutate(n_obs=case_when(gear==4 ~ n_obs*100,
TRUE ~ as.numeric(n_obs))) %>%
group_by(gear) %>%
mutate(n_obs_max=max(n_obs, na.rm=T)) %>%
ggplot()+
geom_bar(aes(y=cyl,
x=n_obs),
stat="identity")+
geom_text(aes(y=cyl,
x=n_obs_max*1.20,
label=n_obs))+
facet_wrap(vars(gear),
scales="free_x")
由 reprex package (v0.3.0)
于 2020 年 3 月 8 日创建
更新
根据下面@stafan 的有用回答,这里是对我的问题的修改和部分回答。
传递给 breaks 参数的函数
my_breaks <- function(x) {
#calculates the max value on the x axis for each facet
new_x=max(x)
#adjusts this max value for a) the extension of the x axis by the
#expand=expansion(mult=c(0, 0.3)) which was needed to have enough space
#for the annotation; and the factor added to the position of the
#annotations with x=max_n_obs*1.10; the result is the maximum value
#of the bars in each facet;
old_max <- new_x/1.3/1.1
#create 5 labels; the maximum is the highest bar in each facet
my_pretty=labeling::extended(0, old_max, m=5)
#round these values
my_pretty=signif(my_pretty, digits=-2)
#remove the highest label(s)
my_pretty=head(unique(my_pretty), -1)
#combine the remaining labels and the maximum value of the highest bar
my_pretty=c(my_pretty, old_max)
my_pretty
}
应用于我的(修改后的)示例,这产生了我一直在寻找的东西(见下图)。
library(tidyverse)
#> Warning: package 'dplyr' was built under R version 3.6.2
#> Warning: package 'forcats' was built under R version 3.6.3
my_breaks <- function(x) {
new_x=max(x)
old_max <- new_x/1.2/1.05
#old_max
my_pretty=labeling::extended(0, old_max, m=5)
my_pretty=signif(my_pretty, digits=-2)
my_pretty=head(unique(my_pretty), -1)
my_pretty=c(my_pretty, old_max)
my_pretty
}
mtcars %>%
group_by(cyl, gear) %>%
summarise(n_obs=n()) %>%
mutate(n_obs=case_when(gear==4 ~ n_obs*100,
TRUE ~ as.numeric(n_obs))) %>%
group_by(gear) %>%
mutate(n_obs_max=max(n_obs, na.rm=T)) %>%
ggplot()+
geom_bar(aes(y=cyl,
x=n_obs),
stat="identity")+
geom_text(aes(y=cyl,
x=n_obs_max*1.20,
label=n_obs))+
scale_x_continuous(breaks=my_breaks1,
expand=expansion(mult=c(0, 0.05)))+
facet_wrap(vars(gear),
scales="free_x")
此函数的一个缺点是比例扩展值 (1.3) 和标签定位因子 (1.1) 被“硬编码”到函数中。方便的是在 ggplot scale 命令中传递函数时指定这些值,例如
scale_x_continuous(breaks=my_breaks(expansion=1.3, pos.factor=1.1))
不幸的是,我还没弄明白这是怎么回事。
由 reprex package (v0.3.0)
于 2020-03-09 创建
试试这个。
- 我扩大了y轴。
- 我调整了休息时间。我借鉴了here的大意。函数
my_breaks
returns pretty_breaks 但删除最后一个值。
(注意:我也切换了美学,y = nobs 和 x = cyl 并使用 coord_flip,因为 运行 你的代码在我的机器上没有重现你的情节(ggplot 3.3.0 )):
library(tidyverse)
#> Warning: package 'forcats' was built under R version 3.6.3
my_breaks <- function(x, n = 5, drop = 2) {
breaks <- seq(x[[1]], x[[2]], length.out = n)
breaks <- scales::pretty_breaks()(breaks)
breaks <- breaks[1:(length(breaks) - drop)]
breaks
}
mtcars %>%
group_by(cyl, gear) %>%
summarise(n_obs = n()) %>%
mutate(n_obs = case_when(
gear == 4 ~ n_obs * 100,
TRUE ~ as.numeric(n_obs))) %>%
group_by(gear) %>%
mutate(n_obs_max = max(n_obs, na.rm=T)) %>%
ggplot(aes(x = cyl))+
geom_bar(aes(y = n_obs), stat="identity")+
geom_text(aes(y = n_obs_max * 1.2, label = n_obs))+
facet_wrap(vars(gear), scales = "free_x") +
scale_y_continuous(breaks = function(x) my_breaks(x, 5, 2),
expand = expand_scale(mult = c(0.05, .2))) +
coord_flip()
#> Warning: `expand_scale()` is deprecated; use `expansion()` instead.
由 reprex package (v0.3.0)
于 2020 年 3 月 9 日创建
我经常制作条形图,并将条形图的值另外包含为注释 (geom_text)。通常,我更喜欢这些值右对齐(与将标签放在条形顶部相反)。在绘制多面条形图时,我将这些值放在每个组中的最大值(我之前计算过)加上一点额外的 space,我通过乘以 x 值(我不使用 nudge_x因为它的绝对值可能适合某些方面但不适合其他方面)。
这种方法让我烦恼的是注释下剩余的轴标签。请参见下图(轴标签 15、100 和 2.5)。我想将 x 轴标签限制为(接近于)每个方面的最大值,而不是一直延伸到注释。
我想知道是否有更好的方法可用。
(我知道我可以用 group_split 生成所需的图形,例如拼凑。我感兴趣的是是否有直接的方法来限制每个单独面的轴 limits/labels) .
非常感谢。
library(tidyverse)
#> Warning: package 'dplyr' was built under R version 3.6.2
#> Warning: package 'forcats' was built under R version 3.6.3
mtcars %>%
group_by(cyl, gear) %>%
summarise(n_obs=n()) %>%
mutate(n_obs=case_when(gear==4 ~ n_obs*100,
TRUE ~ as.numeric(n_obs))) %>%
group_by(gear) %>%
mutate(n_obs_max=max(n_obs, na.rm=T)) %>%
ggplot()+
geom_bar(aes(y=cyl,
x=n_obs),
stat="identity")+
geom_text(aes(y=cyl,
x=n_obs_max*1.20,
label=n_obs))+
facet_wrap(vars(gear),
scales="free_x")
由 reprex package (v0.3.0)
于 2020 年 3 月 8 日创建更新
根据下面@stafan 的有用回答,这里是对我的问题的修改和部分回答。
传递给 breaks 参数的函数
my_breaks <- function(x) {
#calculates the max value on the x axis for each facet
new_x=max(x)
#adjusts this max value for a) the extension of the x axis by the
#expand=expansion(mult=c(0, 0.3)) which was needed to have enough space
#for the annotation; and the factor added to the position of the
#annotations with x=max_n_obs*1.10; the result is the maximum value
#of the bars in each facet;
old_max <- new_x/1.3/1.1
#create 5 labels; the maximum is the highest bar in each facet
my_pretty=labeling::extended(0, old_max, m=5)
#round these values
my_pretty=signif(my_pretty, digits=-2)
#remove the highest label(s)
my_pretty=head(unique(my_pretty), -1)
#combine the remaining labels and the maximum value of the highest bar
my_pretty=c(my_pretty, old_max)
my_pretty
}
应用于我的(修改后的)示例,这产生了我一直在寻找的东西(见下图)。
library(tidyverse)
#> Warning: package 'dplyr' was built under R version 3.6.2
#> Warning: package 'forcats' was built under R version 3.6.3
my_breaks <- function(x) {
new_x=max(x)
old_max <- new_x/1.2/1.05
#old_max
my_pretty=labeling::extended(0, old_max, m=5)
my_pretty=signif(my_pretty, digits=-2)
my_pretty=head(unique(my_pretty), -1)
my_pretty=c(my_pretty, old_max)
my_pretty
}
mtcars %>%
group_by(cyl, gear) %>%
summarise(n_obs=n()) %>%
mutate(n_obs=case_when(gear==4 ~ n_obs*100,
TRUE ~ as.numeric(n_obs))) %>%
group_by(gear) %>%
mutate(n_obs_max=max(n_obs, na.rm=T)) %>%
ggplot()+
geom_bar(aes(y=cyl,
x=n_obs),
stat="identity")+
geom_text(aes(y=cyl,
x=n_obs_max*1.20,
label=n_obs))+
scale_x_continuous(breaks=my_breaks1,
expand=expansion(mult=c(0, 0.05)))+
facet_wrap(vars(gear),
scales="free_x")
此函数的一个缺点是比例扩展值 (1.3) 和标签定位因子 (1.1) 被“硬编码”到函数中。方便的是在 ggplot scale 命令中传递函数时指定这些值,例如
scale_x_continuous(breaks=my_breaks(expansion=1.3, pos.factor=1.1))
不幸的是,我还没弄明白这是怎么回事。
由 reprex package (v0.3.0)
于 2020-03-09 创建试试这个。
- 我扩大了y轴。
- 我调整了休息时间。我借鉴了here的大意。函数
my_breaks
returns pretty_breaks 但删除最后一个值。
(注意:我也切换了美学,y = nobs 和 x = cyl 并使用 coord_flip,因为 运行 你的代码在我的机器上没有重现你的情节(ggplot 3.3.0 )):
library(tidyverse)
#> Warning: package 'forcats' was built under R version 3.6.3
my_breaks <- function(x, n = 5, drop = 2) {
breaks <- seq(x[[1]], x[[2]], length.out = n)
breaks <- scales::pretty_breaks()(breaks)
breaks <- breaks[1:(length(breaks) - drop)]
breaks
}
mtcars %>%
group_by(cyl, gear) %>%
summarise(n_obs = n()) %>%
mutate(n_obs = case_when(
gear == 4 ~ n_obs * 100,
TRUE ~ as.numeric(n_obs))) %>%
group_by(gear) %>%
mutate(n_obs_max = max(n_obs, na.rm=T)) %>%
ggplot(aes(x = cyl))+
geom_bar(aes(y = n_obs), stat="identity")+
geom_text(aes(y = n_obs_max * 1.2, label = n_obs))+
facet_wrap(vars(gear), scales = "free_x") +
scale_y_continuous(breaks = function(x) my_breaks(x, 5, 2),
expand = expand_scale(mult = c(0.05, .2))) +
coord_flip()
#> Warning: `expand_scale()` is deprecated; use `expansion()` instead.
由 reprex package (v0.3.0)
于 2020 年 3 月 9 日创建