R - 如果id列是唯一的,则过滤行,或者当id重复时,过滤具有最少NA的行

时间:2018-04-10 18:41:00

标签: r dplyr

我有一个这样的数据框:

set.seed(123)

testdf <- data.frame(id = c(123,124,125,125,126,126,126,127,128,129,130),
                 var01 = c(sample(c("A", "B", "C", NA), 11, TRUE)),
                 var02 = c(sample(c("A", "B", "C", NA), 11, TRUE)),
                 var03 = c(sample(c("A", "B", "C", NA), 11, TRUE)),
                 var04 = c(sample(c("A", "B", "C", NA), 11, TRUE)),
                 var05 = c(sample(c("A", "B", "C", NA), 11, TRUE)),
                 var06 = c(sample(c("A", "B", "C", NA), 11, TRUE)),
                 var07 = c(sample(c("A", "B", "C", NA), 11, TRUE)),
                 var08 = c(sample(c("A", "B", "C", NA), 11, TRUE)),
                 var09 = c(sample(c("A", "B", "C", NA), 11, TRUE)),
                 var10  = c(sample(c("A", "B", "C", NA), 11, TRUE)))

testdf
    id var01 var02 var03 var04 var05 var06 var07 var08 var09 var10
1  123     B     B     C  <NA>     A     A  <NA>     C  <NA>     C
2  124  <NA>     C  <NA>     A     A     A  <NA>     B     A     C
3  125     B     C     C     B     A  <NA>  <NA>     A     A     B
4  125  <NA>     A     C  <NA>     B  <NA>     B     A     C     B
5  126  <NA>  <NA>     C     A     B     B  <NA>     C     B  <NA>
6  126     A     A     C     B  <NA>     C     C     B     C     B
7  126     C     A     B     A     A     A     C  <NA>     B  <NA>
8  127  <NA>     B     A     A     B     B     A     A     A  <NA>
9  128     C  <NA>  <NA>     B  <NA>     B     B     B  <NA>     C
10 129     B  <NA>  <NA>     B     A  <NA>     A  <NA>     A     B
11 130  <NA>     C     C     B     C     B     B  <NA>     B     A

我想根据两个条件过滤行:

1)具有唯一ID的行。

2)当ID重复时,我想保留该行中具有最少NA的行。

我想要的输出存在除4,5和7之外的所有行。 您可以假设每个id连续出现的最小NAs只发生一次(因此id为125时为2,示例中为126)。

我更喜欢基础R或dplyr解决方案。

非常感谢提前。

2 个答案:

答案 0 :(得分:3)

library(dplyr)
testdf %>% 
  mutate(NAs = rowSums(is.na(.))) %>% 
  group_by(id) %>% 
  filter(NAs == min(NAs)) %>% 
  select(-NAs) %>% 
  ungroup

testdf %>% 
  arrange(id, rowSums(is.na(.))) %>% 
  group_by(id) %>% 
  slice(1) %>% 
  ungroup 

答案 1 :(得分:0)

我注意到几年前我对R缺乏经验时曾问过这个问题。如果对任何人都有用,这可能是最短的解决方案:

testdf %>% 
  arrange(id, rowSums(is.na(.))) %>% 
  distinct(id, .keep_all = T)