ggplots, хранящиеся в списке графиков, чтобы учитывать значения переменных во время создания графика внутри цикла for - PullRequest
2 голосов
/ 17 июня 2020

У меня есть сложная процедура построения графиков, которая генерирует коробчатые графики с дополнительными слоями разброса и добавляет их в список графиков. print(current_plot_complete).

Однако, если они добавляются в список графиков в течение l oop, которое печатается только в конце, то графики неверны: конечные индексы используются для генерации все графики (вместо текущего индекса на момент создания графика). Похоже, это поведение по умолчанию ggplot2, и я ищу решение, чтобы обойти его в текущем варианте использования.

Проблема, похоже, находится в пределах y = eval(parse(text=(paste0(COL_i)))), где используется глобальная среда (и, следовательно, конечное значение индекса) вместо текущих значений на момент выполнения l oop.

Я пробовал различные подходы, чтобы eval () использовать правильные значения переменных, например local(…) или указав среду, но безуспешно.

Очень упрощенный MWE приведено ниже.

enter image description here

MWE

Исходная процедура намного сложнее, чем этот MWE, так что for l oop не может быть легко заменен членами семейства apply.

# create some random data
data_temp <- data.frame(
"a" = sample(x = 1:100, size  = 50),
"b" = rnorm(n = 50, mean = 45, sd = 1),
"c" = sample(x = 20:70, size  = 50), 
"d" = rnorm(n = 50, mean = 40, sd = 15),
"e" = rnorm(n = 50, mean = 50, sd = 10),
"f" = rnorm(n = 50, mean = 45, sd = 1),
"g" = sample(x = 20:70, size  = 50)
)
COLs_current <- c("a", "b", "c", "d", "e") # define COLs of data to include in box plots
choice_COLs <- c("a", "d")      # define COLs of data to add scatter to

plot_list <- list(NA)
plot_index <- 1

for (COL_i in choice_COLs) {

  COL_i_index <- which(COL_i == COLs_current)

  # Generate "basis boxplot" (to plot scatterplot on top)
  boxplot_scores <- data_temp %>% 
    gather(COL, score, all_of(COLs_current)) %>%
    ggplot(aes(x = COL, y = score)) +
    geom_boxplot() 

  # Get relevant data of COL_i for scattering: data of 4th quartile
  quartile_values <- quantile(data_temp[[COL_i]])
  threshold <- quartile_values["75%"]           # threshold = 3. quartile value
  data_temp_filtered <- data_temp %>%
    filter(data_temp[[COL_i]] > threshold) %>%  # filter the data of the 4th quartile
    dplyr::select(COLs_current)                 

  # Create layer of scatter for 4th quartile of COL_i
  scatter_COL_i <- geom_point(data=data_temp_filtered, mapping = aes(x = COL_i_index, y = eval(parse(text=(paste0(COL_i))))), color= "orange")

  # add geom objects to create final plot for COL_i
  current_plot_complete <- boxplot_scores + scatter_COL_i 

  print(current_plot_complete)

  plot_list[[plot_index]] <- current_plot_complete 
  plot_index <- plot_index + 1
}

plot_list

Ответы [ 2 ]

1 голос
/ 17 июня 2020

Я предлагаю это решение, которое не объясняет вам, почему оно не работает так, как вы:

l <- lapply(choice_COLs, temporary_function)

temporary_function <- function(COL_i){
    COL_i_index <- which(COL_i == COLs_current)

    # Generate "basis boxplot" (to plot scatterplot on top)
    boxplot_scores <- data_temp %>% 
        gather(COL, score, all_of(COLs_current)) %>%
        ggplot(aes(x = COL, y = score)) +
        geom_boxplot() 

    # Get relevant data of COL_i for scattering: data of 4th quartile
    quartile_values <- quantile(data_temp[[COL_i]])
    threshold <- quartile_values["75%"]           # threshold = 3. quartile value
    data_temp_filtered <- data_temp %>%
        filter(data_temp[[COL_i]] > threshold) %>%  # filter the data of the 4th quartile
        dplyr::select(COLs_current)                 

    # Create layer of scatter for 4th quartile of COL_i
    scatter <- geom_point(data=data_temp_filtered,
                          mapping = aes(x = COL_i_index,
                                        y = eval(parse(text=(paste0(COL_i))))),
                          color= "orange")

    # add geom objects to create final plot for COL_i
    current_plot_complete <-  boxplot_scores + scatter

    return(current_plot_complete)
    }

Когда вы используете lapply, у вас нет такой проблемы. Он вдохновлен этим сообщением

1 голос
/ 17 июня 2020

Думаю, проблема в том, что ggplot использует ленивое вычисление. При рендеринге list индекс l oop имеет свое окончательное значение, и оно используется для рендеринга всех графиков в списке.

Этот пост актуален .

...