Игнорировать значения NA при фильтрации с помощью dplyr - PullRequest
0 голосов
/ 09 мая 2019

У меня есть датафрейм, такой как:

> tab
   Groups Species Value
1  Group1     Sp1     1
2  Group1     Sp1     4
3  Group1     Sp2    78
4  Group1     Sp3    NA
5  Group1     Sp4    NA
6  Group2     Sp2     3
7  Group2     Sp3     9
8  Group2     Sp4     8
9  Group3     Sp1     9
10 Group3     Sp3    10
11 Group3     Sp3   110
12 Group3     Sp3    14

и я пытаюсь сохранить группы, где значения <80 </p>

Я пытался:

tab %>%
  group_by(Groups) %>%
    filter(all(Value < 80))

но я не знаю, как игнорировать NA values в фильтре.

Здесь я должен получить:

> tab
   Groups Species Value
1  Group1     Sp1     1
2  Group1     Sp1     4
3  Group1     Sp2    78
4  Group1     Sp3    NA
5  Group1     Sp4    NA
6  Group2     Sp2     3
7  Group2     Sp3     9
8  Group2     Sp4     8

У кого-нибудь есть решение? Спасибо

Что если у меня тоже есть:

> tab
   Groups Species Value sp mrca
1  Group1     Sp1     1  3    3
2  Group1     Sp1     4  3    3
3  Group1     Sp2    78 NA   NA
4  Group1     Sp3    NA  3   12
5  Group1     Sp4    NA  3    3
6  Group2     Sp2     3  2    3
7  Group2     Sp3     9  2    40
8  Group2     Sp4     8 NA   NA
9  Group3     Sp1     9  2    2
10 Group3     Sp3    10  3    3
11 Group3     Sp3   110  3    2
12 Group3     Sp3    14  2    3

и я хочу отфильтровать все группы, которые имеют значения <80 и где sp - mrca = 0: 9 </p>

Я пытался с твоим ответом:

tab %>%
  group_by(Groups) %>%
  filter(all(Value < 80 |is.na(Value))) %>%
  filter((all(abs(sp - mrca) %in% 0:9)|is.na(sp) & is.na(mrca)))

Но, похоже, это не тот код

Я должен получить:

> tab
   Groups Species Value sp mrca
1  Group1     Sp1     1  3    3
2  Group1     Sp1     4  3    3
3  Group1     Sp2    78 NA   NA
4  Group1     Sp3    NA  3   12
5  Group1     Sp4    NA  3    3

Ответы [ 2 ]

3 голосов
/ 09 мая 2019

Мы можем использовать и | с is.na

tab %>%
    group_by(Groups) %>%
    filter(all(Value < 80 |is.na(Value)))
# A tibble: 8 x 3
# Groups:   Groups [2]
#  Groups Species Value
#  <chr>  <chr>   <int>
#1 Group1 Sp1         1
#2 Group1 Sp1         4
#3 Group1 Sp2        78
#4 Group1 Sp3        NA
#5 Group1 Sp4        NA
#6 Group2 Sp2         3
#7 Group2 Sp3         9
#8 Group2 Sp4         8

Проблема в коде OP заключалась в том, что когда мы заключаем all в Value < 80, сравнение возвращает NAдля тех значений, которые равны NA, и теперь all также возвращает NA вместо логического ИСТИНА / ЛОЖЬ, а в filter он автоматически сбрасывает NA по умолчанию

Чтобы лучше понятьпроверьте вывод

tab %>% 
    group_by(Groups) %>% 
    mutate(ind = all(Value < 80))

и разницу здесь

tab %>% 
    group_by(Groups) %>% 
    mutate(ind = all(Value < 80| is.na(Value)))

Или используя data.table

library(data.table)
setDT(tab)[, .SD[all(Value < 80 | is.na(Value))], Groups]

Или используя base R

tab[with(tab, ave(Value < 80  | is.na(Value), Groups, FUN = all)),]

Обновление

Для второго набора данных

tab1 %>% 
    group_by(Groups) %>%
    filter(all(Value < 80 |is.na(Value)),
           all(na.omit(abs(sp-mrca)) %in% 0:9))

data

tab <- structure(list(Groups = c("Group1", "Group1", "Group1", "Group1", 
"Group1", "Group2", "Group2", "Group2", "Group3", "Group3", "Group3", 
"Group3"), Species = c("Sp1", "Sp1", "Sp2", "Sp3", "Sp4", "Sp2", 
"Sp3", "Sp4", "Sp1", "Sp3", "Sp3", "Sp3"), Value = c(1L, 4L, 
78L, NA, NA, 3L, 9L, 8L, 9L, 10L, 110L, 14L)), 
class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"))



tab1 <- structure(list(Groups = c("Group1", "Group1", "Group1", "Group1", 
"Group1", "Group2", "Group2", "Group2", "Group3", "Group3", "Group3", 
"Group3"), Species = c("Sp1", "Sp1", "Sp2", "Sp3", "Sp4", "Sp2", 
"Sp3", "Sp4", "Sp1", "Sp3", "Sp3", "Sp3"), Value = c(1L, 4L, 
78L, NA, NA, 3L, 9L, 8L, 9L, 10L, 110L, 14L), sp = c(3L, 3L, 
NA, 3L, 3L, 2L, 2L, NA, 2L, 3L, 3L, 2L), mrca = c(3L, 3L, NA, 
12L, 3L, 3L, 40L, NA, 2L, 3L, 2L, 3L)), 
class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"))
1 голос
/ 09 мая 2019

Мы можем использовать ave из базы R с subset.Удалите NA строки из данных и найдите группы, у которых all значения меньше 80 и subset это из оригинала tab

subset(tab, Groups %in% unique(with(na.omit(tab), 
            Groups[ave(Value < 80, Groups, FUN = all)])))

#  Groups Species Value
#1 Group1     Sp1     1
#2 Group1     Sp1     4
#3 Group1     Sp2    78
#4 Group1     Sp3    NA
#5 Group1     Sp4    NA
#6 Group2     Sp2     3
#7 Group2     Sp3     9
#8 Group2     Sp4     8
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...