英文:
ggplot line plot: is there a way to depict the data points under or over the line plot depending on what looks better?
问题
我想根据数据MIA_YEAR创建一个线图。它已经看起来相当不错了,但我想将那些(几乎)触及线的数据点移动到图下方。或者用数学术语来说:如果斜率增加,数据点应该在线图下方,如果斜率减小,数据点应该在线上方,而不是所有数据点都在线上方。 到目前为止的样子如下 -->。
这是我的代码。我尝试包括类似这样的内容
vjust = ifelse(diff(Percent) < 0, -0.9, 0.9)
,
但它在ggplot中不起作用,我得到了这个错误,尽管该对象明确位于MIA_YEAR内:(Error in diff(y = Percent) : object 'Percent' not found)
(也许您还可以解释一下为什么它不起作用?)
谢谢你的帮助!
编辑1. 这是数据(我希望我理解了复制的点)
structure(list(YEAR = structure(1:13, .Label = c("1990", "2000",
"2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017",
"2018", "2019", "2020"), class = "factor"), n = c(25L, 27L, 74L,
95L, 79L, 79L, 98L, 98L, 102L, 79L, 101L, 86L, 99L), Percent = c(26.6,
25.23, 36.63, 48.72, 44.63, 36.24, 43.75, 42.24, 44.54, 34.96,
46.98, 35.98, 41.42)), class = c("grouped_df", "tbl_df", "tbl",
"data.frame"), row.names = c(NA, -13L), groups = structure(list(
YEAR = structure(1:13, .Label = c("1990", "2000", "2010",
"2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018",
"2019", "2020"), class = "factor"), .rows = structure(list(
1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -13L), .drop = TRUE))
英文:
I wanted to create a line plot based on the data MIA_YEAR. It already looks quite good but I want to move those data points under the plot that (almost) touch the line. Or in mathematial terms: If the slope increases the data points should be under the line plot and if the slope decreases the data points should be over the plot instead of having all data points over the line. that is how it looks like until now -->.
MIA_Year %>%
ggplot(aes(x = YEAR, y = Percent)) +
geom_line(group=1, color = "steelblue", linewidth = 1) + #group = 1 needed when x is a factor
geom_text(data = MIA_Year, aes(label=n), vjust = -0.9) +
scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, by = 10)) +
labs(x = "", y = "Percent of Articles") +
theme(axis.text.x = element_text(angle = 45, hjust = 1), panel.border = element_rect(fill = NA), panel.background = element_rect(fill = "white"), panel.grid = element_line(colour = "grey85"))
This is my code. I tried including something like this
vjust = ifelse(diff(Percent) < 0, -0.9, 0.9)
,
but it did not work with ggplot, I got this error, although the object definitely is inside of MIA_YEAR: (Error in diff(y = Percent) : object 'Percent' not found)
(maybe you could also explain to me, why it does not work?)
Thanks a lot for your help!
Edit 1. Here is the data (I hope I got the point with the copying right)
structure(list(YEAR = structure(1:13, .Label = c("1990", "2000",
"2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017",
"2018", "2019", "2020"), class = "factor"), n = c(25L, 27L, 74L,
95L, 79L, 79L, 98L, 98L, 102L, 79L, 101L, 86L, 99L), Percent = c(26.6,
25.23, 36.63, 48.72, 44.63, 36.24, 43.75, 42.24, 44.54, 34.96,
46.98, 35.98, 41.42)), class = c("grouped_df", "tbl_df", "tbl",
"data.frame"), row.names = c(NA, -13L), groups = structure(list(
YEAR = structure(1:13, .Label = c("1990", "2000", "2010",
"2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018",
"2019", "2020"), class = "factor"), .rows = structure(list(
1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -13L), .drop = TRUE))
答案1
得分: 2
以下是翻译好的代码部分:
library(ggplot2)
library(dplyr, warn = FALSE)
MIA_Year %>%
ungroup() %>%
arrange(YEAR) %>%
mutate(
sign = c(0, diff(Percent)) < 0,
lead_sign = lead(sign, default = FALSE),
nudge_y = 3 * ifelse(sign & !lead_sign, -1, 1),
vjust = ifelse(sign & !lead_sign, 1, 0)
) %>%
ggplot(aes(x = YEAR, y = Percent)) +
geom_line(group = 1, color = "steelblue", linewidth = 1) +
geom_text(aes(y = Percent + nudge_y, label = n, vjust = vjust)) +
scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, by = 10)) +
labs(x = "", y = "文章百分比") +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
panel.border = element_rect(fill = NA),
panel.background = element_rect(fill = "white"),
panel.grid = element_line(colour = "grey85")
)
请注意,我将"Percent of Articles"翻译为了"文章百分比"。
英文:
Building on your idea, here is a working approach where - as mentioned in my comment - I "nudge" the y position of the labels and use vjust
for the alignment. Also note, that I have taken the lead
first differences or slopes into account to place the labels.
library(ggplot2)
library(dplyr, warn = FALSE)
MIA_Year |>
ungroup() |>
arrange(YEAR) |>
mutate(
sign = c(0, diff(Percent)) < 0,
lead_sign = lead(sign, default = FALSE),
nudge_y = 3 * ifelse(sign & !lead_sign, -1, 1),
vjust = ifelse(sign & !lead_sign, 1, 0)
) |>
ggplot(aes(x = YEAR, y = Percent)) +
geom_line(group = 1, color = "steelblue", linewidth = 1) +
geom_text(aes(y = Percent + nudge_y, label = n, vjust = vjust)) +
scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, by = 10)) +
labs(x = "", y = "Percent of Articles") +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
panel.border = element_rect(fill = NA),
panel.background = element_rect(fill = "white"),
panel.grid = element_line(colour = "grey85")
)
<!-- -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论