Поиск выбросов для всех конкретных подмножеств в R?

#r #loops #filter #outliers

#r #циклы #Фильтр #выбросы

Вопрос:

У меня есть несколько условий и несколько типов измерений в моих данных.
Я хочу, чтобы R давал мне значение выбросов для каждой пары условий и типа измерения отдельно.
Итак, например, допустим, у меня есть 3 условия (1-3) и 3 типа мер (A-C) для нескольких участников со значением x для каждой строки. Я хочу иметь выбросы значений x для condition1amp; measureA, condition2 amp; MeasureB и т. Д.
(мера и условие являются нечисловыми)

Я попытался создать цикл

 for(d in unique(data$measure)){
  for(c in unique(data$condition)){
    data %>%
      filter(measure == d, condition ==c) %>%
      o <- outlier(data$value) %>%
      print(o)
  }
}
  

Идея в том, что R будет проходить через каждое условие и измерять в цикле, и каждый раз выбирать значения, которые соответствуют им, и вычислять выбросы.
Когда я запускаю весь код, я получаю это сообщение об ошибке

 Error in print.default(., o) : invalid printing digits -2147483648
In addition: Warning message:
In print.default(., o) : NAs introduced by coercion to integer range
  

(Если я запускаю его без цикла, например, путем поиска выбросов для определенного условия, он также не может найти функцию канала после первой строки.)

Есть идеи о том, как правильно это закодировать?

Комментарии:

1. Если вы уже используете dplyr , вы намеренно избегаете его встроенной (и более эффективной) group_by функциональности?

Ответ №1:

Вы уже используете dplyr , поэтому я предлагаю вам использовать group_by , поскольку это (для меня) более естественный способ работы с данными.

Кроме того, эта часть имеет неправильный синтаксис:

     data %>%
      filter(measure == d, condition ==c) %>%
      o <- outlier(data$value) %>%
      print(o)
  

Почему?

  1. Они filter(...) %>% должны быть подключены к чему-то, что принимает фрейм, но … вы отправляете выходные данные из filter в назначение o <- outlier(...) (а затем в print(o) , что на самом деле означает print(., o) , где . находится вывод из предыдущей команды.

  2. Кроме того, since o еще не определен при первом запуске… вы должны получить сообщение об object 'o' not found ошибке. Вы не получите его при последующих проходах в цикле, поскольку он существует… но если это так, то это выбросы от предыдущей итерации в циклах. Конечно, не то, что вы должны использовать.

Прямое исправление этого кода может быть:

 for (...) {
  for (...) {
    o <- data %>%
      filter(measure == d, condition ==c) %>%
      do({ data.frame(outliers = outlier(.$value)) })
    print(o)
  }
}
  

где o будет data.frame (ну, tbl_df tibble) с тремя столбцами: measure , condition , и outliers . В do этом случае требуется использование, потому что большинство функций, не связанных с tidyverse, игнорируют group_by группировки, поэтому мы используем do , чтобы обойти эту проблему.

Возможно, это, однако, для замены обоих циклов в одну команду:

 data %>%
  group_by(measure, condition) %>%
  summarize(outliers = outlier(value)) %>%
  ungroup()
  

Я предполагаю, что вам нужны все значения выбросов для каждой уникальной комбинации measure и condition , и что outlier(.) функция возвращает вектор (некоторой длины> = 1). Если выбросы не обнаружены, measure condition пара / не будет включена … если это фактор, то используйте что-то вроде

 data %>%
  group_by(measure, condition) %>%
  summarize(outliers = list(outlier(value))) %>%
  tidyr::unnest(outliers, keep_empty = TRUE) %>%
  ungroup()