我正在使用
ggplot2
来绘制一些图来表示 Likert 量表数据,并且需要排斥一些标签,但不需要排斥其他标签。根据 StackOverflow 上找到的大量答案,我想出了以下代码,但排斥的标签位于绘图上的错误位置。
#### Minimum Working Dataset
### Data Creation
## Initial Tibble
survey <- tibble(
question_n = 1,
answer = c("Somewhat Agree", "Somewhat Disagree", "Strongly Agree", "Strongly Disagree"),
n = c(90, 12, 199, 4),
respondents = 305,
pct = n / respondents
)
## Factor levels for answers
survey$answer <- factor(survey$answer,
levels = c("Strongly Agree", "Somewhat Agree",
"Somewhat Disagree", "Strongly Disagree"))
从这里开始,创建就足够简单了:
ggplot
### Plot
survey %>%
ggplot(aes(x = pct, y = 1, fill = fct_rev(answer))) +
geom_col(color = "black") +
theme_minimal() +
scale_x_continuous(labels = label_percent(),
# Expand so the labels aren't off-plot
expand = expansion(mult = c(0.025, 0.025))) +
scale_y_discrete(labels = NULL) +
geom_label(aes(label = percent_format(accuracy = 1)(pct),
color = fct_rev(answer)),
fill = "white",
size = 3.25,
fontface = "bold",
label.size = 1,
label.r = unit(2.5, "pt"),
show.legend = FALSE,
position = position_stack(vjust = 0.5, reverse = FALSE),) +
scale_fill_manual(values = c("tomato4", "tomato", "royalblue", "royalblue4")) +
scale_color_manual(values = c("tomato4", "tomato", "royalblue", "royalblue4"), guide = "none") +
guides(fill = guide_legend(position = "bottom", nrow = 2, reverse = TRUE)) +
labs(
title = NULL,
subtitle = NULL,
caption = paste("Respondents N =", survey[1,]$respondents),
fill = NULL,
color = NULL,
x = NULL,
y = NULL
)
! “不同意”响应标签相互重叠。所以,我把
geom_label_repel()
改为geom_label()
:geom_label_repel()
技术上可行,但看起来真的很乱。 65%和30%的结果被驳回了,尽管没有必要这样做。所以,最后,我尝试包括两者### Plot
survey %>%
ggplot(aes(x = pct, y = 1, fill = fct_rev(answer))) +
geom_col(color = "black") +
theme_minimal() +
scale_x_continuous(labels = label_percent(),
# Expand so the labels aren't off-plot
expand = expansion(mult = c(0.025, 0.025))) +
scale_y_discrete(labels = NULL) +
geom_label_repel(aes(label = percent_format(accuracy = 1)(pct),
color = fct_rev(answer)),
# Filter data to only less than 5.5% for repel; labels fit otherwise
# data = . %>% filter(pct < 0.055),
fill = "white",
size = 3.25,
fontface = "bold",
label.size = 1,
label.r = unit(2.5, "pt"),
show.legend = FALSE,
position = position_stack(vjust = 0.5, reverse = FALSE),
# Set direction so that repel is only "up" or "down" on plot
direction = "y",
# Set ylim to prevent labels going off the bar
ylim = c(.6, 1.3),
# Set seed so they always place in same position
seed = 12345
) +
scale_fill_manual(values = c("tomato4", "tomato", "royalblue", "royalblue4")) +
scale_color_manual(values = c("tomato4", "tomato", "royalblue", "royalblue4"), guide = "none") +
guides(fill = guide_legend(position = "bottom", nrow = 2, reverse = TRUE)) +
labs(
title = NULL,
subtitle = NULL,
caption = paste("Respondents N =", survey[1,]$respondents),
fill = NULL,
color = NULL,
x = NULL,
y = NULL
)
和
geom_label()
:geom_label_repel()
因此,65% 和 30% 处于正确的位置,但 4% 和 1% 现在处于错误的 x 位置。我尝试了一些方法来调整它,例如向
### Plot
survey %>%
ggplot(aes(x = pct, y = 1, fill = fct_rev(answer))) +
geom_col(color = "black") +
theme_minimal() +
scale_x_continuous(labels = label_percent(),
# Expand so the labels aren't off-plot
expand = expansion(mult = c(0.025, 0.025))) +
scale_y_discrete(labels = NULL) +
geom_label_repel(aes(label = percent_format(accuracy = 1)(pct),
color = fct_rev(answer)),
# Filter data to only less than 5.5% for repel; labels fit otherwise
data = . %>% filter(pct < 0.055),
fill = "white",
size = 3.25,
fontface = "bold",
label.size = 1,
label.r = unit(2.5, "pt"),
show.legend = FALSE,
position = position_stack(vjust = 0.5, reverse = FALSE),
# Set direction so that repel is only "up" or "down" on plot
direction = "y",
# Set ylim to prevent labels going off the bar
ylim = c(.6, 1.3),
# Set seed so they always place in same position
seed = 12345
) +
geom_label(aes(label = percent_format(accuracy = 1)(pct),
color = fct_rev(answer)),
# Filter data to everything greater than 5.5%; no need to repel these items
data = . %>% filter(pct >= 0.055),
fill = "white",
size = 3.25,
fontface = "bold",
label.size = 1,
label.r = unit(2.5, "pt"),
show.legend = FALSE,
position = position_stack(vjust = 0.5, reverse = FALSE),) +
scale_fill_manual(values = c("tomato4", "tomato", "royalblue", "royalblue4")) +
scale_color_manual(values = c("tomato4", "tomato", "royalblue", "royalblue4"), guide = "none") +
guides(fill = guide_legend(position = "bottom", nrow = 2, reverse = TRUE)) +
labs(
title = NULL,
subtitle = NULL,
caption = paste("Respondents N =", survey[1,]$respondents),
fill = NULL,
color = NULL,
x = NULL,
y = NULL
)
添加
x =
值,指定 aes()
位置而不是 nudge_x =
,以及其他一些我现在实际上记不起的东西。在过去的几个小时里我一直在努力解决这个问题。我需要 65% 和 30% 的位置,以及其他两个值,它们应该位于一个轴上,并像在另一个轴上一样进行微调。有什么建议吗?
position_stack()
包,它具有一些有用的位置函数,在本例中为
ggpp
,正如您所猜测的,它允许数据堆叠和微移。但首先您需要按问题和答案排列数据,以控制微移距离需要“长度为1的数字向量,或者与数据中的行长度相同,微移值按数据行顺序排列。” 接下来,识别连续值低于特定阈值的实例,并使用交替符号分配微移偏移值。
您必须根据绘图的宽度和高度修改阈值和偏移值。
使用您的示例数据:
position_stacknudge()
library(ggplot2)
library(ggpp)
library(scales)
library(dplyr)
survey <- tibble(
question_n = 1,
answer = c("Somewhat Agree", "Somewhat Disagree", "Strongly Agree", "Strongly Disagree"),
n = c(90, 12, 199, 4),
respondents = 305,
pct = n / respondents
)
survey$answer <- factor(survey$answer,
levels = c("Strongly Agree", "Somewhat Agree",
"Somewhat Disagree", "Strongly Disagree"))
threshold <- .06
off_y <- .1
survey <- survey %>%
arrange(question_n, answer) %>%
mutate(flag = pct <= threshold,
cid = consecutive_id(flag), .by = question_n) %>%
mutate(offset = if_else(flag & n() > 1, off_y * -cospi(row_number()), 0),
.by = c(question_n, cid))
survey %>%
ggplot(aes(x = pct, y = question_n, fill = fct_rev(answer))) +
geom_col(color = "black") +
theme_minimal() +
scale_x_continuous(labels = label_percent(),
# Expand so the labels aren't off-plot
expand = expansion(mult = c(0.025, 0.025))) +
scale_y_discrete(labels = NULL) +
geom_label(aes(label = percent_format(accuracy = 1)(pct),
color = fct_rev(answer)),
fill = "white",
size = 3.25,
fontface = "bold",
label.size = 1,
label.r = unit(2.5, "pt"),
show.legend = FALSE,
position = position_stacknudge(vjust = 0.5, y = survey$offset, reverse = FALSE),) +
scale_fill_manual(values = c("tomato4", "tomato", "royalblue", "royalblue4")) +
scale_color_manual(values = c("tomato4", "tomato", "royalblue", "royalblue4"), guide = "none") +
guides(fill = guide_legend(position = "bottom", nrow = 2, reverse = TRUE)) +
labs(
title = NULL,
subtitle = NULL,
caption = paste("Respondents N =", survey$respondents[1]),
fill = NULL,
color = NULL,
x = NULL,
y = NULL
)
如上绘图给出: