Как я могу ускорить добавление многих слоев / геом ggplot в цикл for? - PullRequest
1 голос
/ 24 сентября 2019
library(ggplot2)
library(magrittr)
library(data.table)

Nbars = 2

generate_eg_data <- function() {
  eg_data = data.table(LL = 0:99, UL = 1:100, val = sort(runif(100, 0, 1)))
  eg_data[, valColor := val %>% multiply_by(255) %>% ceiling %>% as.hexmode %>% list %>% c(., ., .) %>% do.call(paste0, .) %>% paste0("#", .)]
  return(eg_data)
}

lst_eg_data <- lapply(seq(Nbars), function(i) {
  return(generate_eg_data())
})

p <- ggplot() +
  scale_x_continuous(limits = c(0, 100)) +
  scale_y_continuous(limits = c(0, Nbars + 1)) +
  theme_classic()
for (i in seq(Nbars)) {
  for (j in seq(nrow(lst_eg_data[[i]]))) {
    p %<>% add(geom_ribbon(data = lst_eg_data[[i]][j, .(x = c(LL, UL), ymin = rep(i - 0.25, 2), ymax = rep(i + 0.25, 2))],
                           aes(x = x, ymin = ymin, ymax = ymax),
                           fill = lst_eg_data[[i]][j, valColor]))
  }
}
p

Вышесказанного должно быть достаточно для демонстрации желаемых результатов.Для простоты, в приведенном выше примере я сгенерировал аналогичные valColor для каждого столбца, но в действительности каждый столбец сильно различается в зависимости от различных комбинаций RGB (т. Е. Не только в оттенках серого).

Код работает, но он простослишком медленно, потому что на самом деле у меня есть 6 баров на каждом графике и 36 таких графиков вместе с некоторыми другими вспомогательными слоями, которые я бы хотел поместить в один график с помощью gridExtra::arrangeGrob.Процесс длился более часа, и он еще не завершен.

Мне интересно, так ли это, потому что я пытаюсь добавить каждую полосу, используя 100 отдельных слоев.Если это так, возможно ли добавить каждый столбец как отдельный слой, сохранив уникальную схему окраски, определенную для каждого столбца?Или есть другие причины медленных сюжетов, и как я могу сделать их более эффективными?Спасибо!

1 Ответ

1 голос
/ 24 сентября 2019

Цикл замедляет все это, и это не обязательно, плохой стиль, и его следует избегать.Скорее, внешняя петля (i) должна соответствовать y-эстетике, а внутренняя петля (j) должна соответствовать x-эстетике.(Помимо этого, обычно вместо %<>% используется скорее что-то вроде p <- p + geom_ribbon().)

Вот подход, использующий geom_tile(), но могут также подойти и другие гемы.Обратите внимание, что сначала я превращаю ваш список из двух фреймов данных (lst_eg_data) в один фрейм данных.

df1 <- melt(lst_eg_data, id.vars = names(lst_eg_data[[1]]))

ggplot(df1, aes(x = LL, y = L1, fill = valColor, height = .5)) +
    scale_fill_grey() +
    geom_tile(show.legend = FALSE)
...