Dplyr сделать несколько графиков в анонимной функции - PullRequest
0 голосов
/ 05 октября 2018

Я хотел бы использовать do, чтобы создать несколько ggplots на основе сгруппированного фрейма данных, но внести изменения в график, а именно изменить ось Y, если столбец содержит определенное значение.

Iсмоделировал мой подход после ответа Хэдли на этот вопрос: dplyr :: do () требует именованной функции?

У меня проблема с получением объекта gg во фрейм данных для его возвратаКак мне вручную сделать то, что do автоматически сделало в моем рабочем примере ниже, и «обернуть» объект gg чем-то, что можно поместить во фрейм данных?

df <-   data.frame( position=rep(seq(0,99),2),
                    strand=c(rep("-",100),rep("+",100)),
                    score=rnorm(200),
                    gene=c(rep("alpha",100),rep("beta",100))
        )

Это прекрасно работает:

plots <- df %>% 
    group_by(gene) %>%
    do(plot=
        ggplot(.,aes(position,score)) +
            geom_point()
    )
plots   

Результат:

# A tibble: 2 x 2
  gene  plot    
* <fct> <list>  
1 alpha <S3: gg>
2 beta  <S3: gg>

Это не:

plots <- df %>% 
    group_by(gene) %>%
    do({
        plot <- ggplot(.,aes(position,score)) +
            geom_point()

        if (all(.$strand=="-")) {
            plot <- plot + scale_y_reverse()
        }
        data.frame(., plot) ##!! <<< how to get the ggplot object into a data frame
    })
plots

Сбой с ошибкой:

Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) : 
  cannot coerce class "c("gg", "ggplot")" to a data.frame

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Мы можем использовать вложенный фрейм данных вместо do:

library(ggplot2)
library(tidyverse)

plots <- df %>%
  group_by(gene) %>%
  nest() %>%
  mutate(plots = data %>% map(~{
    plot <- ggplot(.,aes(position,score)) +
      geom_point()

    if (all(.$strand=="-")) {
      plot <- plot + scale_y_reverse()
    }
    return(plot)
  })) %>%
  select(-data) 

Вывод:

# A tibble: 2 x 2
  gene  plots   
  <fct> <list>  
1 alpha <S3: gg>
2 beta  <S3: gg>

enter image description here enter image description here

0 голосов
/ 05 октября 2018

Я не думаю, что вам нужно, чтобы возвращаемое значение было фреймом.Попробуйте это:

plots <- df %>% 
    group_by(gene) %>%
    do(plot= {
        p <- ggplot(.,aes(position,score)) +
            geom_point()
        if (all(.$strand == "-")) p <- p + scale_y_reverse()
        p
    })
plots
# Source: local data frame [2 x 2]
# Groups: <by row>
# # A tibble: 2 x 2
#   gene  plot    
# * <fct> <list>  
# 1 alpha <S3: gg>
# 2 beta  <S3: gg>

Я думаю, что одна проблема в том, что ваша условная логика в порядке, но вы не назвали блок в пределах do(...).

. Вы можете просмотреть один из них с помощью:

plots$plot[[1]]

sample plot

Если вы хотите сбросить все графики (например, в документе уценки), просто наберите plots$plot, и они будут циклически повторятьсядовольно быстро (не так полезно на консоли).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...