Сообщение об ошибке при использовании Dplyr для фильтрации с более чем 3 уровнями к фактору - PullRequest
0 голосов
/ 27 сентября 2018

Я пытаюсь отфильтровать некоторые факторы в Dplyer, но вместо того, чтобы вручную выписывать те, которые я хотел, например, c («синий», «зеленый», «белый») и т. Д., Я вычислил что-то вроде

levels(df$factor.variable)[1:3]

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

a <- 1:20
b <- rep(c("Blue", "Green", "White", "Grey"),5)
df <- data.frame(Numbers=a, colours=b)
df %>% 
  select(Numbers, colours) %>% 
  filter(colours==levels(df$colours)[1:3])

Обратите внимание, что если вы выберете только 1 или 2 уровня выше (как в [1] или [1: 2], не[1: 3]), тогда проблема не возникает.Также, если я уберу один из цветов (факторов), у меня больше не будет проблем.

a <- 1:15
b <- rep(c("Blue", "Green", "White"),5)
df <- data.frame(Numbers=a, colours=b)
df %>% 
  select(Numbers, colours) %>% 
  filter(colours==levels(df$colours)[1:3])

Какие объекты имеют более длинную / более короткую длину?И почему исчезает 2/3 данных?

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Это на самом деле не проблема dplyr.

Как уже упоминалось, a == b проверяет, идентична ли каждая пара элементов, то есть a[1] == b[1], a[2] == b[2] и т. Д.(Взгляните на ?Comparison.) Вы сравниваете векторы неодинаковой длины и с длинами, которые не пригодны для повторного использования одного из них, чтобы соответствовать другому, что и является причиной того, что вы получили предупреждение.

Вместо этого a %in% b проверяет, существует ли каждый элемент в a где-нибудь в b, и возвращает true или false для каждого элемента в a.

Для иллюстрации с вашими данными:

library(dplyr)

a <- 1:20
b <- rep(c("Blue", "Green", "White", "Grey"),5)
df <- data.frame(Numbers=a, colours=b)

В представлении a %in% b это ваша b:

levels(df$colours)[1:3]
#> [1] "Blue"  "Green" "Grey"

Проверка наличия каждого элемента colours в этом наборе значений дает логическоеvector:

df$colours %in% levels(df$colours)[1:3]
#>  [1]  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE
#> [12]  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE

Базовая версия R dplyr::filter выглядит следующим образом, принимая элементы df$colours, для которых предыдущая операция дает TRUE:

df$colours[df$colours %in% levels(df$colours)[1:3]]
#>  [1] Blue  Green Grey  Blue  Green Grey  Blue  Green Grey  Blue  Green
#> [12] Grey  Blue  Green Grey 
#> Levels: Blue Green Grey White

Indplyr, нестандартная оценка отбрасывает необходимость в df$, но вы делаете по существу то же самое в dplyr::filter: обнаружение, находится ли каждый элемент colours в подмножестве значений levels(colours)[1:3], а затемфильтрация только для тех строк, которые соответствуют TRUE.

df %>%
  filter(colours %in% levels(colours)[1:3])
#>    Numbers colours
#> 1        1    Blue
#> 2        2   Green
#> 3        4    Grey
#> 4        5    Blue
#> 5        6   Green
#> 6        8    Grey
#> 7        9    Blue
#> 8       10   Green
#> 9       12    Grey
#> 10      13    Blue
#> 11      14   Green
#> 12      16    Grey
#> 13      17    Blue
#> 14      18   Green
#> 15      20    Grey
0 голосов
/ 27 сентября 2018

Вы делали ошибку в dplyr.Вместо == использование% в% решило ошибку.

a <- 1:20
b <- rep(c("Blue", "Green", "White", "Grey"),5)
df <- data.frame(Numbers=a, colours=b)
str(df)

df2<- df %>% 
  select(Numbers, colours) %>% 
  filter(colours %in% levels(df$colours)[1:3])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...