Я понимаю, что у многих людей возникнут проблемы с использованием цикла for для создания этого графика, а не с предпочтительным методом R для объединения данных, но ради того, насколько я уже близок, пожалуйста, подшутите над мной.
У меня есть несколько наборов данных, которые я хотел бы обработать и создать график, представляющий столбец всех из них. Я достиг этого до сих пор:
singleden <- function (){
line_list <- vector("list", length(paths))
for (i in (1:length(paths))) {
# dirname <- dirname(paths[i])
# len <- nchar(dirname)
# corename <- (substr(dirname, 97, len))
line_list[[i]] <- geom_line(data = datas[[i]], aes(x = year, y = density, group =1),
stat = "identity", color = color[i])
}
label_list <- vector("list", length(paths))
for (i in (1:length(paths))) {
name <- basename(dirname(paths[i]))
# directname <- dirname(paths[i])
# #print(paths[i])
# #print(directname)
#
# name <- (substr(directname, 97, len))
label_list[[i]] <- geom_label_repel(data = datas[[i]] %>% filter (year == min(year)),
aes(label = name, y = density, x = year), color = color[i])
}
ggplot() + line_list + label_list
}
Линии рисуются правильно, и все в порядке.
введите сюда описание изображения
Однако добавление label_list генерирует метки только с последним значением списка. Каким-то образом мои два списка кажутся смещенными при построении их с помощью ggplot. В самом списке хранятся правильные числа и значения, которые я ожидал бы при печати.
введите сюда описание изображения
Я пробовал использовать один цикл for как для строк, так и для меток, столкнулся с той же проблемой. Интересно, нужно ли мне как-то объединить списки, но неясно, как это сделать.
Проблема связана с ленивой оценкой, и есть множество вопросов, в которых люди сталкиваются с одной и той же проблемой при использовании циклов for
. См., например. Цикл for добавляет только последний слой ggplot для объяснения проблемы.
В вашем случае этой проблемы, скорее всего, можно избежать, переместив label = name
за пределы aes()
.
Использование минимального воспроизводимого примера на основе набора данных gapminder
:
library(gapminder)
library(ggplot2)
library(ggrepel)
library(dplyr, warn=FALSE)
set.seed(123)
datas <- gapminder |>
filter(country %in% sample(levels(gapminder$country), 5)) |>
rename(density = lifeExp) |>
split(~country, drop = TRUE)
color <- gapminder::country_colors[names(datas)]
paths <- file.path(names(datas), names(datas))
singleden <- function() {
line_list <- vector("list", length(paths))
for (i in (1:length(paths))) {
line_list[[i]] <- geom_line(
data = datas[[i]], aes(x = year, y = density, group = 1),
stat = "identity", color = color[i]
)
}
label_list <- vector("list", length(paths))
for (i in (1:length(paths))) {
name <- basename(dirname(paths[i]))
label_list[[i]] <- geom_label_repel(
data = datas[[i]] %>% filter(year == min(year)),
aes(y = density, x = year), color = color[i], label = name
)
}
ggplot() + line_list + label_list
}
singleden()
Однако в целом я бы рекомендовал использовать lapply
для создания list
графиков или слоев с помощью «цикла», что в целом позволяет избежать проблемы:
singleden2 <- function() {
line_label_list <- lapply(
seq_along(paths), \(i) {
name <- basename(dirname(paths[i]))
list(
geom_line(
data = datas[[i]], aes(x = year, y = density, group = 1),
stat = "identity", color = color[i]
),
geom_label_repel(
data = datas[[i]] %>% filter(year == min(year)),
aes(label = name, y = density, x = year), color = color[i]
)
)
}
)
ggplot() + line_label_list
}
singleden2()
Но, насколько я понимаю, чего вы пытаетесь достичь, я предпочитаю связать ваш список наборов данных в один и использовать только один geom_line
и geom_label_repel
для построения графика:
names(datas) <- names(color) <- basename(dirname(paths))
datas |>
bind_rows(.id = "name") |>
ggplot(aes(x = year, y = density, group = name, color = name)) +
geom_line() +
geom_label_repel(
data = ~ filter(., year == min(year), .by = name),
aes(label = name), direction = "y", show.legend = FALSE
) +
scale_color_manual(values = color, guide = "none")
Огромное спасибо, перемещение имени за пределы aes сработало хорошо, я обязательно попробую и другие методы, чтобы улучшить свои навыки R. Приятно знать, что эта проблема касается не только меня.