在data.frame中删除具有NAs(缺失值)的行

我想删除这个数据框中所有列中包含NA的行。 以下是我的示例数据框。

  gene hsap mmul mmus rnor cfam 1 ENSG00000208234 0 NA NA NA NA 2 ENSG00000199674 0 2 2 2 2 3 ENSG00000221622 0 NA NA NA NA 4 ENSG00000207604 0 NA NA 1 2 5 ENSG00000207431 0 NA NA NA NA 6 ENSG00000221312 0 1 2 3 2 

基本上,我想要得到如下的数据框。

  gene hsap mmul mmus rnor cfam 2 ENSG00000199674 0 2 2 2 2 6 ENSG00000221312 0 1 2 3 2 

另外,我想知道如何只过滤一些列,所以我也可以得到这样的数据框:

  gene hsap mmul mmus rnor cfam 2 ENSG00000199674 0 2 2 2 2 4 ENSG00000207604 0 NA NA 1 2 6 ENSG00000221312 0 1 2 3 2 

同时检查complete.cases

 > final[complete.cases(final), ] gene hsap mmul mmus rnor cfam 2 ENSG00000199674 0 2 2 2 2 6 ENSG00000221312 0 1 2 3 2 

na.omit更好地删除所有的NAcomplete.cases允许通过仅包含dataframe的某些列来进行部分select:

 > final[complete.cases(final[ , 5:6]),] gene hsap mmul mmus rnor cfam 2 ENSG00000199674 0 2 2 2 2 4 ENSG00000207604 0 NA NA 1 2 6 ENSG00000221312 0 1 2 3 2 

您的解决scheme无法工作。 如果你坚持使用is.na ,那么你必须做一些事情:

 > final[rowSums(is.na(final[ , 5:6])) == 0, ] gene hsap mmul mmus rnor cfam 2 ENSG00000199674 0 2 2 2 2 4 ENSG00000207604 0 NA NA 1 2 6 ENSG00000221312 0 1 2 3 2 

但使用complete.cases的案例更清晰,更快。

试试na.omit(your.data.frame) 。 至于第二个问题,请尝试将其作为另一个问题(为了清楚起见)。

我更喜欢下面的方式来检查行是否包含任何NAs:

 row.has.na <- apply(final, 1, function(x){any(is.na(x))}) 

这将返回逻辑向量,其值表示一行中是否有任何NA。 您可以使用它来查看您需要删除多less行:

 sum(row.has.na) 

并最终放弃他们

 final.filtered <- final[!row.has.na,] 

对于使用某些部分NAs过滤行,它变得有点棘手(例如,您可以将'final [,5:6]'提供给'apply')。 一般来说,Joris Meys的解决scheme似乎更加优雅。

另一个select,如果你想更好地控制行被认为是无效的是

 final <- final[!(is.na(final$rnor)) | !(is.na(rawdata$cfam)),] 

使用以上这个:

  gene hsap mmul mmus rnor cfam 1 ENSG00000208234 0 NA NA NA 2 2 ENSG00000199674 0 2 2 2 2 3 ENSG00000221622 0 NA NA 2 NA 4 ENSG00000207604 0 NA NA 1 2 5 ENSG00000207431 0 NA NA NA NA 6 ENSG00000221312 0 1 2 3 2 

变为:

  gene hsap mmul mmus rnor cfam 1 ENSG00000208234 0 NA NA NA 2 2 ENSG00000199674 0 2 2 2 2 3 ENSG00000221622 0 NA NA 2 NA 4 ENSG00000207604 0 NA NA 1 2 6 ENSG00000221312 0 1 2 3 2 

…其中只有第5行被删除,因为它是rnorcfam唯一包含rnor cfam 。 然后可以改变布尔逻辑以适应特定的要求。

如果您想要控制每行有效的NAs数量,请尝试使用此function。 对于许多调查数据集来说,太多的空白问题反应会破坏结果。 所以他们在一定的门槛后被删除。 这个函数可以让你select行被删除之前有多less个NAs。

 delete.na <- function(DF, n=0) { DF[rowSums(is.na(DF)) <= n,] } 

默认情况下,它将消除所有的NAs:

 delete.na(final) gene hsap mmul mmus rnor cfam 2 ENSG00000199674 0 2 2 2 2 6 ENSG00000221312 0 1 2 3 2 

或者指定允许的最大NAs数量:

 delete.na(final, 2) gene hsap mmul mmus rnor cfam 2 ENSG00000199674 0 2 2 2 2 4 ENSG00000207604 0 NA NA 1 2 6 ENSG00000221312 0 1 2 3 2 

如果你喜欢pipe( %>% ), tidyr的新drop_na是你的朋友:

 library(tidyr) df %>% drop_na() # gene hsap mmul mmus rnor cfam # 2 ENSG00000199674 0 2 2 2 2 # 6 ENSG00000221312 0 1 2 3 2 df %>% drop_na(rnor, cfam) # gene hsap mmul mmus rnor cfam # 2 ENSG00000199674 0 2 2 2 2 # 4 ENSG00000207604 0 NA NA 1 2 # 6 ENSG00000221312 0 1 2 3 2 

这将返回至less有一个非NA值的行。

 final[rowSums(is.na(final))<length(final),] 

这将返回至less有两个非NA值的行。

 final[rowSums(is.na(final))<(length(final)-1),] 

我们也可以使用这个子集函数。

 finalData<-subset(data,!(is.na(data["mmul"]) | is.na(data["rnor"]))) 

这将只给出mmul和rnor中没有NA的那些行

对于你的第一个问题,我有一个我很熟悉的代码来摆脱所有的NAs。 感谢@Gregor使它更简单。

 final[!(rowSums(is.na(final))),] 

对于第二个问题,代码只是从以前的解决scheme的一个替代。

 final[as.logical((rowSums(is.na(final))-5)),] 

请注意,-5是数据中的列数。 这将消除所有NA的行,因为rowSums加起来为5,减法后它们变成零。 这一次,逻辑是必要的。

希望你喜欢!

我是一个合成器:)。 在这里,我将这些答案组合成一个函数:

 #' keep rows that have a certain number (range) of NAs anywhere/somewhere and delete others #' @param df a data frame #' @param col restrict to the columns where you would like to search for NA; eg, 3, c(3), 2:5, "place", c("place","age") #' \cr default is NULL, search for all columns #' @param n integer or vector, 0, c(3,5), number/range of NAs allowed. #' \cr If a number, the exact number of NAs kept #' \cr Range includes both ends 3<=n<=5 #' \cr Range could be -Inf, Inf #' @return returns a new df with rows that have NA(s) removed #' @export ez.na.keep = function(df, col=NULL, n=0){ if (!is.null(col)) { # R converts a single row/col to a vector if the parameter col has only one col # see https://radfordneal.wordpress.com/2008/08/20/design-flaws-in-r-2-%E2%80%94-dropped-dimensions/#comments df.temp = df[,col,drop=FALSE] } else { df.temp = df } if (length(n)==1){ if (n==0) { # simply call complete.cases which might be faster result = df[complete.cases(df.temp),] } else { # credit: http://stackoverflow.com/a/30461945/2292993 log <- apply(df.temp, 2, is.na) logindex <- apply(log, 1, function(x) sum(x) == n) result = df[logindex, ] } } if (length(n)==2){ min = n[1]; max = n[2] log <- apply(df.temp, 2, is.na) logindex <- apply(log, 1, function(x) {sum(x) >= min && sum(x) <= max}) result = df[logindex, ] } return(result) } 

使用dplyr包,我们可以如下过滤NA:

 dplyr::filter(df, !is.na(columnname)) 

假设dat为你的dataframe,预期的输出可以使用

1. rowSums

 > dat[!rowSums((is.na(dat))),] gene hsap mmul mmus rnor cfam 2 ENSG00000199674 0 2 2 2 2 6 ENSG00000221312 0 1 2 3 2 

2. lapply

 > dat[!Reduce('|',lapply(dat,is.na)),] gene hsap mmul mmus rnor cfam 2 ENSG00000199674 0 2 2 2 2 6 ENSG00000221312 0 1 2 3 2 
Interesting Posts