Как сделать "постоянные" графики с помощью ggplot для ggarrange до и после обработки данных в R - PullRequest
2 голосов
/ 07 мая 2020

Я пытаюсь создать графики сравнения данных до и после обработки данных для нескольких столбцов в моем наборе данных с помощью for l oop. В конце концов, я хочу сохранить все сравнительные графики в один файл pdf. Во-первых, я создаю график раньше, манипулирую данными, генерирую график после и хочу, чтобы они располагались бок о бок через ggarrange (я также пробовал grid.arrange из gridExtra, но это не решает проблему). Однако я получаю идентичные графики ПОСЛЕ обработки данных (хотя названия разные).

Вот воспроизводимый пример:

library(rlist)
library(ggplot2)
library(ggpubr)
head(iris)
plot_before <-  list()
plot_after <- list()
plots <- list()

for (i in 1:4){
  p <-  ggplot(iris,aes(iris[,i])) + geom_histogram()+ggtitle(paste0(i,"_pre"))
  print(p)
  plot_before <- list.append(plot_before,p)
  #do something with your data
  iris[,i] <- 3*iris[,i]
  p2 <-  ggplot(iris,aes(iris[,i])) + geom_histogram()+ggtitle(paste0(i,"_post"))
  print(p2)
  plot_after <- list.append(plot_after, p2)
  q <-  ggarrange(p,p2)  #here, p is already linked to modified data
  print(q)
  plots <- list.append(plots, q)
}
#try to access plots from lists
for (i in 1:4){
  print(plot_before[[i]])
  print(plot_after[[i]])
  print(plots[[i]])
}

Я полагаю, это имеет какое-то отношение к тому, что ggplot создает «только» графический объект, связанный с данными, поэтому в тот момент, когда я напечатаю его снова , он снова обращается к данным и извлекает обработанные данные вместо получения предыдущего «снимка». Сохранение графиков в отдельные списки также не помогает, они также «связаны» с обрабатываемыми данными.

Есть ли способ создать постоянный объект ggplot вместо того, чтобы связывать его с данными?

Можно, конечно, создать новые столбцы с измененными данными и ссылаться на них или создать совершенно новый фрейм данных, но я бы хотел избежать дублирования данных.

1 Ответ

4 голосов
/ 07 мая 2020

Помогает пакет пэчворк. Можно создать список графиков, а затем сгладить список и использовать patchwork::wrap_plots.

Еще один способ ggplot - избегать использования векторов в aes. Я включил способ создания aes.

update

Согласно вашему комментарию - вы не хотите дважды изменять данные и не хотите сохранять лишние столбцы. Теперь l oop и модифицирует данные, и создает список желаемых графиков.

library(tidyverse)
library(patchwork)

p_list <- list()
sel_col <- names(iris)[1:4]

for(i in sel_col){
  p <-  ggplot(iris, aes(!!sym(i))) +
    geom_histogram()+
    ggtitle(paste0(i,"_pre"))

  p_list[[i]][["pre"]] <- p

  iris[i] <- 3*iris[,i ]

  p2 <- ggplot(iris, aes(!!sym(i))) + 
    geom_histogram()+
    ggtitle(paste0(i,"_post"))

  p_list[[i]][["post"]] <- p2
}

head(iris) # iris has changed
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1         15.3        10.5          4.2         0.6  setosa
#> 2         14.7         9.0          4.2         0.6  setosa
#> 3         14.1         9.6          3.9         0.6  setosa
#> 4         13.8         9.3          4.5         0.6  setosa
#> 5         15.0        10.8          4.2         0.6  setosa
#> 6         16.2        11.7          5.1         1.2  setosa

ls_unnest <- do.call(list, unlist(p_list, recursive=FALSE))

wrap_plots(ls_unnest, ncol = 2)

Создано 07.05.2020 с помощью пакета REPEX (v0.3.0)

Полезная ветка: Как выровнять список списков?

...