Фильтровать строки по двум критериям - PullRequest
0 голосов
/ 19 мая 2018

Мой фрейм данных выглядит следующим образом:

Key   Year    Type
A     2000    ok
A     2001    ok
A     2001    notok
A     2002    ok
A     2003    ok
B     2000    ok
B     2001    ok
B     2001    ok
B     2002    ok
B     2003    ok
C     2000    ok
C     2001    ok
C     2002    ok
C     2003    ok

Я ищу код, который возвращает мне все буквы в ключе моего столбца, если есть два наблюдения за определенный год с одним из них, говорящим«notok» и другие «ок» в моем типе столбца.Я не хочу, чтобы в моем новом фрейме данных был ключ b, хотя за один год есть 2 наблюдения.Это потому, что в моей колонке Type оба наблюдения отмечены ок.

Поэтому ответ должен выглядеть следующим образом:

Key   Year    Type
A     2000    ok
A     2001    ok
A     2001    notok
A     2002    ok
A     2003    ok

Есть ли простой код для этого?

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

Использование data.table:

library(data.table)
setDT(df)

# option 1
df[Key %in% df[, .SD[uniqueN(Type) == 2], by = .(Key, Year)][, unique(Key)] ]

# option 2
df[, .SD[any(.SD[, uniqueN(Type), by = Year]$V1 == 2)], by = Key]

# option 3
df[, if (any(.SD[, uniqueN(Type), by = Year]$V1 == 2)) .SD, by = Key]

, что дает:

   Key Year  Type
1:   A 2000    ok
2:   A 2001    ok
3:   A 2001 notok
4:   A 2002    ok
5:   A 2003    ok

Та же логика, что и для dplyr:

library(dplyr)
k <- df %>% 
  group_by(Key, Year) %>% 
  filter(n_distinct(Type) == 2) %>% 
  distinct(Key) %>% 
  pull(Key)

df %>% filter(Key %in% k )

Или с основанием R:

k <- unique(df$Key[with(df, ave(Type, Key, Year, FUN = function(x) length(unique(x)))) == 2])
df[df$Key %in% k, ]
0 голосов
/ 19 мая 2018

Если это также учитывает столбец «Год», то мы должны сгруппировать по «Ключу» и «Году»

df1 %>%
   group_by(Key, Year) %>% 
   mutate(n = sum(c("ok", "notok") %in% Type)) %>% 
   group_by(Key) %>% 
   filter(any(n == 2)) %>%
   select(-n)
# A tibble: 5 x 3
# Groups:   Key [1]
#  Key    Year Type 
#  <chr> <int> <chr>
#1 A      2000 ok   
#2 A      2001 ok   
#3 A      2001 notok
#4 A      2002 ok   
#5 A      2003 ok   

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

i1 <- with(df1, ave(ave(Type, Key, Year, FUN = 
        function(x) length(unique(x)))==2, Key, FUN = any))
df1[i1,]
# Key Year  Type
#1   A 2000    ok
#2   A 2001    ok
#3   A 2001 notok
#4   A 2002    ok
#5   A 2003    ok

Или используя split с table

subset(df1, Key %in% names(which(sapply(split(df1[-1], Key), 
     function(x) ncol(table(x))==2))))

Исходя из ожидаемого результата, после группировки по «Ключу», filter эти «Ключ имеет оба»ok "и" notok "%in% столбец 'Type'

df1 %>%
  group_by(Key) %>% 
  filter(all(c("ok", "notok") %in% Type))
# A tibble: 5 x 3
# Groups:   Key [1]
#  Key    Year Type 
#  <chr> <int> <chr>
#1 A      2000 ok   
#2 A      2001 ok   
#3 A      2001 notok
#4 A      2002 ok   
#5 A      2003 ok   

Если в 'Type' есть только 'ok' и 'notok', мы можем подсчитать количество уникальных элементов до filter

df1 %>% 
   group_by(Key) %>%
   filter(n_distinct(Type)==2)

data

df1 <- structure(list(Key = c("A", "A", "A", "A", "A", "B", "B", "B", 
"B", "B", "C", "C", "C", "C"), Year = c(2000L, 2001L, 2001L, 
2002L, 2003L, 2000L, 2001L, 2001L, 2002L, 2003L, 2000L, 2001L, 
2002L, 2003L), Type = c("ok", "ok", "notok", "ok", "ok", "ok", 
"ok", "ok", "ok", "ok", "ok", "ok", "ok", "ok")), class = "data.frame", row.names = c(NA, 
-14L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...