如果列中的NA数大于3,则删除数据帧行

时间:2014-05-31 12:49:34

标签: r dataframe na

我有一个数据框(面板数据):Ctry列表示数据框中国家/地区的名称。在任何列(例如:Carx)中,如果NA的数量大于3;我想把相关国家放在我的数据名声中。例如,

  • 国家A有2个NA
  • 国家B有4个NA
  • 国家/地区C有3 NA

我想在我的数据框中删除国家/地区。我有一个这样的数据框(这是为了说明,我的数据框实际上非常巨大):

  Ctry  year   Carx
   A    2000    23
   A    2001    18
   A    2002    20
   A    2003    NA
   A    2004    24
   A    2005    18
   B    2000    NA
   B    2001    NA
   B    2002    NA
   B    2003    NA
   B    2004    18
   B    2005    16
   C    2000    NA
   C    2001    NA
   C    2002    24
   C    2003    21
   C    2004    NA
   C    2005    24

我想创建一个这样的数据框:

  Ctry  year   Carx
   A    2000    23
   A    2001    18
   A    2002    20
   A    2003    NA
   A    2004    24
   A    2005    18
   C    2000    NA
   C    2001    NA
   C    2002    24
   C    2003    21
   C    2004    NA
   C    2005    24

3 个答案:

答案 0 :(得分:3)

基础R中一种相当简单的方法是使用sum(is.na(.))ave进行计数,如下所示:

with(mydf, ave(Carx, Ctry, FUN = function(x) sum(is.na(x))))
#  [1] 1 1 1 1 1 1 4 4 4 4 4 4 3 3 3 3 3 3

完成后,子集很容易:

mydf[with(mydf, ave(Carx, Ctry, FUN = function(x) sum(is.na(x)))) <= 3, ]
#    Ctry year Carx
# 1     A 2000   23
# 2     A 2001   18
# 3     A 2002   20
# 4     A 2003   NA
# 5     A 2004   24
# 6     A 2005   18
# 13    C 2000   NA
# 14    C 2001   NA
# 15    C 2002   24
# 16    C 2003   21
# 17    C 2004   NA
# 18    C 2005   24

答案 1 :(得分:2)

您可以使用by()功能按Ctry分组,并计算每组的NA个:

DF <- read.csv(
text='Ctry,year,Carx
A,2000,23
A,2001,18
A,2002,20
A,2003,NA
A,2004,24
A,2005,18
B,2000,NA
B,2001,NA
B,2002,NA
B,2003,NA
B,2004,18
B,2005,16
C,2000,NA
C,2001,NA
C,2002,24
C,2003,21
C,2004,NA
C,2005,24',
stringsAsFactors=F)

res <- by(data=DF$Carx,INDICES=DF$Ctry,FUN=function(x)sum(is.na(x)))
validCtry <-names(res)[res <= 3]

DF[DF$Ctry %in% validCtry, ]

#   Ctry year Carx
#1     A 2000   23
#2     A 2001   18
#3     A 2002   20
#4     A 2003   NA
#5     A 2004   24
#6     A 2005   18
#13    C 2000   NA
#14    C 2001   NA
#15    C 2002   24
#16    C 2003   21
#17    C 2004   NA
#18    C 2005   24

编辑:

如果要检查更多列,可以按如下方式调整以前的代码:

res <- by(data=DF,INDICES=DF$Ctry,
          FUN=function(x){
                           return(sum(is.na(x$Carx)) <= 3 && 
                                  sum(is.na(x$Barx)) <= 3 && 
                                  sum(is.na(x$Tarx)) <= 3)
                         })
validCtry <- names(res)[res]

DF[DF$Ctry %in% validCtry, ]

当然,您可以根据需要更改FUN中的条件。

答案 2 :(得分:1)

既然你提到你的数据“非常庞大”(无论这意味着什么),你可以尝试使用dplyr的解决方案,看看它是否比基础R中的解决方案更快。如果其他解决方案是足够快,只要忽略这个。

require(dplyr)

newdf <- df %.% group_by(Ctry) %.% filter(sum(is.na(Carx)) <= 3)