英文:
Avoid cut geom_label() with facet_wrap()
问题
在下图中,我将数据分为四组,通过 facet_wrap()
进行分隔。然而,这些组的数据分布不均匀,因此所有组的柱形大小都不同。
如何避免切割第一组和第二组的 geom_label()
?
geom_label(aes(label = str_glue('{round(prop, 1.5)}%')),
nudge_y = 15,
nudge_x = 0.3,
colour = 'black',
fill = "yellow",
label.padding = unit(0.125, "lines"),
size = 3.5,
clip = "on") + # 添加这一行
奖励:是否有一种动态设置 geom_label()
的方式,使标签始终粘附到根据每个柱形大小设置的特定位置?(因此,我不必手动设置它们,具有不同数据量的组可以在相同的位置获取标签)?
修改:
我需要一个解决方案来实现这一点:
geom_label(aes(label = str_glue('n = {n}')),
size = 2,
nudge_x = 0.3,
nudge_y = 30,
fontface = "italic",
show.legend = FALSE,
clip = "on") + # 添加这一行
数据:
df <- structure(list(CH = structure(c(3L, 2L, 3L, 2L, 3L, 4L, 5L, 6L,
7L, 6L, 7L), .Label = c("Não oferta", "1h - 3h", "4h - 5h", "6h - 8h",
"9h - 10h", "Mais de 10h", "50% em LA"), class = "factor"), Q9 = structure(c(1L,
2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L), .Label = c("one", "two",
"three", "four"), class = "factor"), n = c(1L, 12L, 1L, 8L, 2L,
2L, 2L, 1L, 3L, 2L, 2L), prop = c(100, 92.31, 7.69, 44.44, 11.11,
11.11, 11.11, 5.56, 16.67, 50, 50), sd = c(NA, 0.6, 0.6, 0.14,
0.14, 0.14, 0.14, 0.14, 0.14, 0, 0)), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -11L), groups = structure(list(
Q9 = structure(1:4, .Label = c("one", "two", "three", "four"
), class = "factor"), .rows = structure(list(1L, 2:3, 4:9,
10:11), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -4L), .drop = TRUE))
英文:
in the plot below I have data distributed into four groups separated via facet_wrap()
. However, these groups have an uneven distribution of the data, hence, all groups have different bar sizes.
How can I avoid cut the geom_label() of groups one and two ?
Here is my code:
library(tidyverse)
library(RColorBrewer)
###
cor12 <- brewer.pal(12, "Paired")
cor5 <- brewer.pal(7, "Pastel1")
myColors <- c(cor12, cor5)
names(myColors) <- c('Não oferta',
'1h - 3h',
'4h - 5h',
'6h - 8h',
'9h - 10h',
'Mais de 10h', 'Mais de 15h',
'20h', 'Mais de 20h', 'Mais de 30h',
'50% em LA', '100% em LA')
### plot:
df %>%
ggplot(aes(y = prop, x = fct_rev(CH), fill = CH, pattern = Q9)) +
geom_bar(stat = "identity", width = 0.5) +
scale_fill_manual(values = myColors, name = NULL) +
geom_label(aes(label = str_glue('{round(prop, 1.5)}%')),
nudge_y = 15, #15
nudge_x = 0.3, #0.05
colour = 'black',
fill = "yellow",
label.padding = unit(0.125, "lines"),
size = 3.5) +
### FLIP IT:
coord_flip(clip = "off") +
facet_wrap(~Q9, scales = "free_y") +
### SHOW N
geom_label(aes(label= str_glue('n = {n}')),
size = 2,
nudge_x = 0.3,
nudge_y = 30,
fontface = "italic",
show.legend = FALSE) +
### SHOW % IN THE X-AXIS:
scale_y_continuous(limits = c(0,100),
labels=scales::percent_format(scale = 1)) +
### LABELS:
labs(x = "times",
y = '%',
title = "a title") +
### THEME:
cowplot::theme_half_open() +
theme(
text = element_text(family = "sans",
size = 14,
hjust = 0.5),
#plot.margin = margin(t = 0, r = 15, b = 0, l = 0),
legend.position = "bottom",
legend.justification = "center",
legend.background = element_rect(color = "black"), #bloco com legendas
legend.margin = margin(t = 5, r = 5, b = 3, l = 3),
legend.text = element_text(size = 12),
axis.text.x = element_text(hjust = 0.5,
size = 12), # legenda de baixo
axis.title.x = element_text(size = 13.5,
face = "bold",
margin = margin(t = 20, r = 0, b = 0, l = 0)),
axis.text.y = element_text(size = 12),
axis.title.y = element_text(size = 13.5,
face = "bold"),
### Facets:
strip.text.x = element_text(face = "bold",
family = "sans",
size = 18,
colour = 'green'),
strip.background = element_rect(size = 3,
fill = 'yellow'),
strip.switch.pad.grid = unit('10', "cm"),
strip.clip = "off")
QUESTIONS:
1: How can I avoid cut the geom_label()
of groups one and two ?
Bonus : is there a way to dynamically set geom_label()
so that the labels always get stuck to a certain position according to each bar size? (hence, I don't have to set them manually and groups with different amount of data get the labels at the same place) ?
Edits:
I need a solution to achieve this:
Data:
structure(list(CH = structure(c(3L, 2L, 3L, 2L, 3L, 4L, 5L, 6L,
7L, 6L, 7L), .Label = c("Não oferta", "1h - 3h", "4h - 5h", "6h - 8h",
"9h - 10h", "Mais de 10h", "50% em LA"), class = "factor"), Q9 = structure(c(1L,
2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L), .Label = c("one", "two",
"three", "four"), class = "factor"), n = c(1L, 12L, 1L, 8L, 2L,
2L, 2L, 1L, 3L, 2L, 2L), prop = c(100, 92.31, 7.69, 44.44, 11.11,
11.11, 11.11, 5.56, 16.67, 50, 50), sd = c(NA, 0.6, 0.6, 0.14,
0.14, 0.14, 0.14, 0.14, 0.14, 0, 0)), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -11L), groups = structure(list(
Q9 = structure(1:4, .Label = c("one", "two", "three", "four"
), class = "factor"), .rows = structure(list(1L, 2:3, 4:9,
10:11), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -4L), .drop = TRUE))
答案1
得分: 1
以下是翻译好的部分:
更新后的澄清:这不是最佳解决方案,但对于这个示例应该可以工作。为了避免由于将一个标签移到左边而导致丢失一个标签,我们可以通过更改两个(%和n)nudge_x和nudge_y来叠加标签,然后我们可以看到它们全部:
df %>%
ggplot(aes(y = prop, x = fct_rev(CH), fill = CH, pattern = Q9)) +
geom_bar(stat = "identity", width = 0.5) +
scale_fill_manual(values = myColors, name = NULL) +
geom_label(aes(label = str_glue('{round(prop, 1.5)}%')),
nudge_y = -2, #15
nudge_x = 0.05, #0.05
colour = 'black',
fill = "yellow",
label.padding = unit(0.125, "lines"),
size = 3.5) +
### 翻转图表:
coord_flip(clip = "off") +
facet_wrap(~Q9, scales = "free_y") +
### 显示 N
geom_label(aes(label= str_glue('n = {n}')),
size = 2,
nudge_x = -0.2,
nudge_y = -2,
fontface = "italic",
show.legend = FALSE) +
### 在X轴上显示百分比:
scale_y_continuous(limits = c(0,100),
labels=scales::percent_format(scale = 1)) +
### 标签:
labs(x = "times",
y = '%',
title = "a title") +
### 主题:
cowplot::theme_half_open() +
theme(
text = element_text(family = "sans",
size = 14,
hjust = 0.5),
#plot.margin = margin(t = 0, r = 15, b = 0, l = 0),
legend.position = "bottom",
legend.justification = "center",
legend.background = element_rect(color = "black"), #带有图例的块
legend.margin = margin(t = 5, r = 5, b = 3, l = 3),
legend.text = element_text(size = 12),
axis.text.x = element_text(hjust = 0.5,
size = 12), #底部图例
axis.title.x = element_text(size = 13.5,
face = "bold",
margin = margin(t = 20, r = 0, b = 0, l = 0)),
axis.text.y = element_text(size = 12),
axis.title.y = element_text(size = 13.5,
face = "bold"),
### 分面:
strip.text.x = element_text(face = "bold",
family = "sans",
size = 18,
colour = 'green'),
strip.background = element_rect(size = 3,
fill = 'yellow'),
strip.switch.pad.grid = unit('10', "cm"),
strip.clip = "off")
第一个答案:
这应该能够满足您的要求:
为了避免将y轴扩展到超过100%,我们可以将标签定位在图表区域内。
在这里,我们使用prop
条件来设置标签的y位置:
df %>%
ggplot(aes(y = prop, x = fct_rev(CH), fill = CH, pattern = Q9)) +
geom_bar(stat = "identity", width = 0.5) +
scale_fill_manual(values = myColors, name = NULL) +
geom_label(aes(label = str_glue('{round(prop, 1.5)}%'), y = ifelse(prop < 10, prop + 5, prop - 5)),
colour = 'black',
fill = "yellow",
label.padding = unit(0.125, "lines"),
size = 3.5) +
coord_flip(clip = "off") +
facet_wrap(~Q9, scales = "free_y") +
scale_y_continuous(limits = c(0,100), labels=scales::percent_format(scale = 1)) +
theme(
text = element_text(family = "sans", size = 14, hjust = 0.5),
legend.position = "bottom",
legend.justification = "center",
# 其他主题元素...
)+
### 标签:
labs(x = "times",
y = '%',
title = "a title") +
### 主题:
cowplot::theme_half_open() +
theme(
text = element_text(family = "sans",
size = 14,
hjust = 0.5),
#plot.margin = margin(t = 0, r = 15, b = 0, l = 0),
legend.position = "bottom",
legend.justification = "center",
legend.background = element_rect(color = "black"), #带有图例的块
legend.margin = margin(t = 5, r = 5, b = 3, l = 3),
legend.text = element_text(size = 12),
axis.text.x = element_text(hjust = 0.5,
size = 12), #底部图例
axis.title.x = element_text(size = 13.5,
face = "bold",
margin = margin(t = 20, r = 0, b = 0, l = 0)),
axis.text.y = element_text(size = 12),
axis.title.y = element_text(size = 13.5,
face = "bold"),
### 分面:
strip.text.x = element_text(face = "bold",
family = "sans",
size = 18,
colour = 'green'),
strip.background = element_rect(size = 3,
fill = 'yellow'),
strip.switch.pad.grid = unit('10', "cm"),
strip.clip = "off")
英文:
Update after clarification: It is not the best solution but it should work for this example. To avoid losing one label because of moving the other to the left, we could stack the labels by changing both (% and n) nudge_x and nudge_y and then we can see all of them:
df %>%
ggplot(aes(y = prop, x = fct_rev(CH), fill = CH, pattern = Q9)) +
geom_bar(stat = "identity", width = 0.5) +
scale_fill_manual(values = myColors, name = NULL) +
geom_label(aes(label = str_glue('{round(prop, 1.5)}%')),
nudge_y = -2, #15
nudge_x = 0.05, #0.05
colour = 'black',
fill = "yellow",
label.padding = unit(0.125, "lines"),
size = 3.5) +
### FLIP IT:
coord_flip(clip = "off") +
facet_wrap(~Q9, scales = "free_y") +
### SHOW N
geom_label(aes(label= str_glue('n = {n}')),
size = 2,
nudge_x = -0.2,
nudge_y = -2,
fontface = "italic",
show.legend = FALSE) +
### SHOW % IN THE X-AXIS:
scale_y_continuous(limits = c(0,100),
labels=scales::percent_format(scale = 1)) +
### LABELS:
labs(x = "times",
y = '%',
title = "a title") +
### THEME:
cowplot::theme_half_open() +
theme(
text = element_text(family = "sans",
size = 14,
hjust = 0.5),
#plot.margin = margin(t = 0, r = 15, b = 0, l = 0),
legend.position = "bottom",
legend.justification = "center",
legend.background = element_rect(color = "black"), #bloco com legendas
legend.margin = margin(t = 5, r = 5, b = 3, l = 3),
legend.text = element_text(size = 12),
axis.text.x = element_text(hjust = 0.5,
size = 12), # legenda de baixo
axis.title.x = element_text(size = 13.5,
face = "bold",
margin = margin(t = 20, r = 0, b = 0, l = 0)),
axis.text.y = element_text(size = 12),
axis.title.y = element_text(size = 13.5,
face = "bold"),
### Facets:
strip.text.x = element_text(face = "bold",
family = "sans",
size = 18,
colour = 'green'),
strip.background = element_rect(size = 3,
fill = 'yellow'),
strip.switch.pad.grid = unit('10', "cm"),
strip.clip = "off")
First answer:
This should do what you are after:
To avoid expanding y axis over 100%, we could position the labels in the chart area.
Here we use prop
in a condition to set y position of the labels:
df %>%
ggplot(aes(y = prop, x = fct_rev(CH), fill = CH, pattern = Q9)) +
geom_bar(stat = "identity", width = 0.5) +
scale_fill_manual(values = myColors, name = NULL) +
geom_label(aes(label = str_glue('{round(prop, 1.5)}%'), y = ifelse(prop < 10, prop + 5, prop - 5)),
colour = 'black',
fill = "yellow",
label.padding = unit(0.125, "lines"),
size = 3.5) +
coord_flip(clip = "off") +
facet_wrap(~Q9, scales = "free_y") +
scale_y_continuous(limits = c(0,100), labels=scales::percent_format(scale = 1)) +
theme(
text = element_text(family = "sans", size = 14, hjust = 0.5),
legend.position = "bottom",
legend.justification = "center",
# Other theme elements...
)+
### LABELS:
labs(x = "times",
y = '%',
title = "a title") +
### THEME:
cowplot::theme_half_open() +
theme(
text = element_text(family = "sans",
size = 14,
hjust = 0.5),
#plot.margin = margin(t = 0, r = 15, b = 0, l = 0),
legend.position = "bottom",
legend.justification = "center",
legend.background = element_rect(color = "black"), #bloco com legendas
legend.margin = margin(t = 5, r = 5, b = 3, l = 3),
legend.text = element_text(size = 12),
axis.text.x = element_text(hjust = 0.5,
size = 12), # legenda de baixo
axis.title.x = element_text(size = 13.5,
face = "bold",
margin = margin(t = 20, r = 0, b = 0, l = 0)),
axis.text.y = element_text(size = 12),
axis.title.y = element_text(size = 13.5,
face = "bold"),
### Facets:
strip.text.x = element_text(face = "bold",
family = "sans",
size = 18,
colour = 'green'),
strip.background = element_rect(size = 3,
fill = 'yellow'),
strip.switch.pad.grid = unit('10', "cm"),
strip.clip = "off")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论