Условный фильтр с dplyr - PullRequest
1 голос
/ 10 мая 2019

вот кадр данных:

  cluster_names Species values   Nsp Nsp_MRCA Event NB_Event Nsp_losses
 1 Group1        Sp1          1     3        3     1        2          0
 2 Group1        Sp1          4     3        3     1        2          0
 3 Group1        Sp2         78    NA       NA     1        2         NA
 4 Group1        Sp3         NA     3       12     2        2          9
 5 Group1        Sp4         NA     3        3     2        2          0
 6 Group2        Sp2          3     2        3     2        2          1
 7 Group2        Sp3          9     2       40     2        2         38
 8 Group2        Sp4          8    NA       NA     2        2         NA
 9 Group3        Sp1          9     2        2     1        1          0
10 Group3        Sp3         10     3        3     1        1          0
11 Group3        Sp3         12     3       20     1        1         17
12 Group3        Sp3         14     2        3     1        1          1
13 Group4        Sp4         23     3      112     1        1        109
14 Group5        Sp3         34     5      114     1        1        109
15 Group6        Sp4          2     3        3     1        1          0

Как можно сказать с deplyr, хранить только Groups, где:

  • Nsp > 1 по крайней мере для one row
  • Nsp == Nsp_MRCA хотя бы для одной строки
  • Все Nsp_losses < 3 исключают, если все Nsp находятся между 5 и 2 и все Nsp_losses < 20
  • ВсеNB_Event должно быть < 3

Вот с таким фильтром я должен получить новый df:

  cluster_names Species values   Nsp Nsp_MRCA Event NB_Event Nsp_losses
 1 Group1        Sp1          1     3        3     1        2          0
 2 Group1        Sp1          4     3        3     1        2          0
 3 Group1        Sp2         78    NA       NA     1        2         NA
 4 Group1        Sp3         NA     3       12     2        2          9
 5 Group1        Sp4         NA     3        3     2        2          0
 9 Group3        Sp1          9     2        2     1        1          0
10 Group3        Sp3         10     3        3     1        1          0
11 Group3        Sp3         12     3       20     1        1         17
12 Group3        Sp3         14     2        3     1        1          1
15 Group6        Sp4          2     3        3     1        1          0

Деталь:

  • Group1 сохраняется, поскольку Nsp находятся между 5 и 2, а все Nsp_losses < 20
  • Group2 удаляются, поскольку Nsp_losses = 38
  • Group3 сохраняются, посколькуNsp находятся между 5 и 2, и все Nsp_losses < 20
  • Groups 4 и 5 удалены, потому что Nsp_losses = 38
  • Group6 сохраняется, потому что Nsp == Nsp_MRCA хотя бы для одной строки

, и у всех этих есть хотя бы одна строка с Nsp> 1

До сих пор я пробовал следующий код:

tab %>%
  group_by(cluster_names) %>%
    mutate(NB_Event = max(Event,na.rm=TRUE))  %>%
    filter(any(Nsp > 1 |is.na(Nsp))) %>%
    filter(any(Nsp == Nsp_MRCA)) %>%
    mutate(Nsp_losses = abs(Nsp - Nsp_MRCA)) %>%
    filter(all(Nsp <=5 |is.na(Nsp)) & all(Nsp > 1 |is.na(Nsp) & all(Nsp_losses < 20 |is.na(Nsp_losses))))  %>%

Вот датафрейм

structure(list(cluster_names = structure(c(1L, 1L, 1L, 1L, 1L, 
2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 5L, 6L), .Label = c("Group1", 
"Group2", "Group3", "Group4", "Group5", "Group6"), class = "factor"), 
    Species = structure(c(1L, 1L, 2L, 3L, 4L, 2L, 3L, 4L, 1L, 
    3L, 3L, 3L, 4L, 3L, 4L), .Label = c("Sp1", "Sp2", "Sp3", 
    "Sp4"), class = "factor"), values = c(1L, 4L, 78L, NA, NA, 
    3L, 9L, 8L, 9L, 10L, 12L, 14L, 23L, 34L, 2L), Nsp = c(3L, 
    3L, NA, 3L, 3L, 2L, 2L, NA, 2L, 3L, 3L, 2L, 3L, 5L, 3L), 
    Nsp_MRCA = c(3L, 3L, NA, 12L, 3L, 3L, 40L, NA, 2L, 3L, 20L, 
    3L, 112L, 114L, 3L), Event = c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 
    2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L)), class = "data.frame", row.names = c(NA, 
-15L))

Спасибо за вашу помощь и время.

Ответы [ 3 ]

2 голосов
/ 10 мая 2019

Наличие NA s делает его немного сложным, поэтому я сначала удаляю их, используя na.omit, и выясняю группы (cluster_names), которые удовлетворяют заданным условиям, а затем filter на их основе.

library(dplyr)

tab %>%
  filter(cluster_names %in% (tab %>%
  na.omit() %>%
  mutate(Nsp_losses = abs(Nsp - Nsp_MRCA)) %>%
  group_by(cluster_names) %>%
  filter(any(Nsp > 1 & Nsp == Nsp_MRCA) & all(Event < 3) &
       (if(all(Nsp %in% 2:5)) all(Nsp_losses < 20) else all(Nsp_losses < 3))) %>%
   pull(cluster_names) %>% unique))


#  cluster_names Species values Nsp Nsp_MRCA Event
#1         Group1     Sp1      1   3        3     1
#2         Group1     Sp1      4   3        3     1
#3         Group1     Sp2     78  NA       NA     1
#4         Group1     Sp3     NA   3       12     2
#5         Group1     Sp4     NA   3        3     2
#6         Group3     Sp1      9   2        2     1
#7         Group3     Sp3     10   3        3     1
#8         Group3     Sp3     12   3       20     1
#9         Group3     Sp3     14   2        3     1
#10        Group6     Sp4      2   3        3     1
2 голосов
/ 10 мая 2019

Мы могли бы сделать:

     tab %>% 
      group_by(cluster_names) %>% 
      mutate(Nsp_losses = abs(Nsp - Nsp_MRCA),
Cond=ifelse(Nsp_losses < 20 & between(Nsp,2,5) || Nsp==Nsp_MRCA ,1,0)) %>% 
      filter(Cond==1) %>% 
     filter(all(Nsp_losses)<20)  %>% 
      select(-Cond)


 cluster_names Species values   Nsp Nsp_MRCA Event Nsp_losses
   <fct>         <fct>    <int> <int>    <int> <int>      <int>
 1 Group1        Sp1          1     3        3     1          0
 2 Group1        Sp1          4     3        3     1          0
 3 Group1        Sp2         78    NA       NA     1         NA
 4 Group1        Sp3         NA     3       12     2          9
 5 Group1        Sp4         NA     3        3     2          0
 6 Group3        Sp1          9     2        2     1          0
 7 Group3        Sp3         10     3        3     1          0
 8 Group3        Sp3         12     3       20     1         17
 9 Group3        Sp3         14     2        3     1          1
10 Group6        Sp4          2     3        3     1          0
1 голос
/ 10 мая 2019

Предполагая, что у вас уже есть NB_Event и Nsp_losses переменные, и построчно воссоздайте свой текст:

library(tidyverse)

dat %>%
  group_by(cluster_names) %>%
  filter(
      any(Nsp > 1, na.rm = T)         & 
      any(Nsp == Nsp_MRCA, na.rm = T) & 
      all(NB_Event < 3, na.rm = T)    &
      all(Nsp_losses < 3, na.rm = T)  | 
      all(
        between(na.omit(Nsp), 2, 5)   & 
        all(Nsp_losses < 20, na.rm = T)
        )
    ) %>%
  ungroup()

Какие выходные данные:

# A tibble: 10 x 8
   cluster_names Species values   Nsp Nsp_MRCA Event NB_Event Nsp_losses
   <fct>         <fct>    <int> <int>    <int> <int>    <dbl>      <int>
 1 Group1        Sp1          1     3        3     1        2          0
 2 Group1        Sp1          4     3        3     1        2          0
 3 Group1        Sp2         78    NA       NA     1        2         NA
 4 Group1        Sp3         NA     3       12     2        2          9
 5 Group1        Sp4         NA     3        3     2        2          0
 6 Group3        Sp1          9     2        2     1        2          0
 7 Group3        Sp3         10     3        3     1        2          0
 8 Group3        Sp3         12     3       20     1        2         17
 9 Group3        Sp3         14     2        3     1        2          1
10 Group6        Sp4          2     3        3     1        2          0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...