Проверьте наличие объекта ggplot NULL перед добавлением слоев в трубу dplyr. - PullRequest
1 голос
/ 19 февраля 2020

У меня есть функции шаблонного графика, которые проверяют, имеет ли фрейм данных> 0 строк перед запуском:

library(tidyverse)

plot_fun <- function(df) {
  if (nrow(df) > 0) {
    df %>%
      ggplot(., aes(Sepal.Length, Sepal.Width)) +
      geom_point()
  } 
}

Затем я использую это в каналах и добавляю сделанные на заказ слои:

iris %>% plot_fun() + ggtitle("Plot me")

enter image description here

Однако, если данные в кадре имеют 0 строк, я получаю сообщение об ошибке, потому что я пытаюсь добавить слои ни к чему:

iris %>% 
  filter(Sepal.Length > 1000) %>% 
  plot_fun() +
  ggtitle("Plot me")

Ошибка в ирисе%>% filter (Sepal.Length> 1000)%>% plot_fun () + ggtitle ("Plot me"): не числовой c аргумент бинарного оператора

I может построить чек в середине канала, чтобы избежать ошибки:

iris %>%
  filter(Sepal.Length > 1000) %>%
  plot_fun() %>%
  {
    if (!is.null(.)) {
      . +
        ggtitle("Plot me")
    }
  }

Это работает, но кажется неуклюжим. Можно ли сделать функцию check_df_pipe() или что-то, чтобы остановить канал, если предыдущие фильтры удаляют все данные? Или, может быть, проверить, является ли канал . NULL в точке?

check_df_pipe <- function(x) {
  if(nrow(x) > 0) {
    x 
  } else{
    stop("Dont return an error just to exit pipe")
  }
}

iris %>%
  filter(Sepal.Length > 1000) %>%
  check_df_pipe() %>% 
  plot_fun() +
  ggtitle("Plot me")

Ошибка в check_df_pipe (.): Не возвращать ошибку только для выхода из трубы

Или есть другие идеи о том, как с этим бороться? Я не хочу добавлять ggtitle("Plot me") в plot_fun, потому что я не хочу plot_fun оставаться универсальным c.

Ответы [ 2 ]

2 голосов
/ 19 февраля 2020

Вариант 1: Пустой сюжет

Это не дает прямого ответа на ваш вопрос, но как насчет другого подхода? Когда в кадре данных ноль строк, используйте geom_blank(), чтобы создать пустой график. Добавление заголовка позже не возвращает ошибку.

plot_fun <- function(df) {
  if (nrow(df) > 0) {
    df %>%
      ggplot(., aes(Sepal.Length, Sepal.Width)) +
      geom_point()
  } else {
    ggplot(data = data.frame()) +
      geom_blank()
  }
}

iris %>% 
  filter(Sepal.Length > 1000) %>% 
  plot_fun() +
  ggtitle("Plot me")

Вариант 2. Передача слоев в функцию

Вы можете передавать слои в качестве аргументов функции. Вот функция, которая проверяет, существует ли график, а затем добавляет слои, только если это так.

append_layers_maybe <- function(p, l) {
  if(!is.null(p)) {
    p + l
  }
}

iris %>%
  plot_fun() %>%
  append_layers_maybe(facet_wrap(~ Species)) %>%
  append_layers_maybe(ggtitle("Foo"))

iris %>%
  filter(Sepal.Length > 1000) %>%
  plot_fun() %>%
  append_layers_maybe(facet_wrap(~ Species)) %>%
  append_layers_maybe(ggtitle("Plot me"))
1 голос
/ 19 февраля 2020

Я бы не рекомендовал такой трубопровод. Это может сбивать с толку, чтобы декодировать такой код. Но вот решение:

cond_pipe <- function(x) {
  if (nrow(x) > 0) {
    x %>%
      plot_fun() +
      ggtitle("Plot me")
  } else {
    warning("Dont return an error just to exit pipe")
  }
}

iris %>%
  filter(Sepal.Length > 1000) %>%
  cond_pipe()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...