我有一个大的数据集,包含11列和100000行(以此类推),其中值为1、2、3、4。其中4是缺失值。有些行完全缺失,即所有11列都是4。例如:
"4" "4" "4" "4" "4" "4" "4" "4" "4" "4" "4"
现在我需要做的是仅删除那些完全缺失的行。简单来说,我想保留缺少小于11个值的行。 我已经使用了na.omit,但它在我的情况下不起作用。
提前致谢。
我有一个大的数据集,包含11列和100000行(以此类推),其中值为1、2、3、4。其中4是缺失值。有些行完全缺失,即所有11列都是4。例如:
"4" "4" "4" "4" "4" "4" "4" "4" "4" "4" "4"
现在我需要做的是仅删除那些完全缺失的行。简单来说,我想保留缺少小于11个值的行。 我已经使用了na.omit,但它在我的情况下不起作用。
提前致谢。
NA
值的习惯用法。一旦您编码了NA
值,就可以使用complete.cases
轻松实现您的目标。set.seed(123)
m <- matrix(sample(1:4, 30, prob=c(0.3, 0.3, 0.3, 0.1), replace=TRUE), ncol=6)
m[4, ] <- rep(4, 6)
将所有值等于4的值替换为NA
:
m[m==4] <- NA
m
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 NA 2 2 2
[2,] 2 3 3 1 2 3
[3,] 3 2 2 1 2 3
[4,] NA NA NA NA NA NA
[5,] NA 3 1 NA 2 1
现在你可以使用多种处理NA
值的函数。例如,complete.cases
函数将仅返回已完整的数据行:
m[complete.cases(m), ]
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 2 3 3 1 2 3
[2,] 3 2 2 1 2 3
想要了解更多信息,请查看stats
包中的?complete.cases
或?na.fail
。
set.seed(123)
m <- matrix(sample(1:4, 30, prob=c(0.3, 0.3, 0.3, 0.1), replace=TRUE), ncol=6)
m[4, ] <- rep(4, 6)
m[m==4] <- NA
m
这是初始数据集:
1 1 NA 2 2 2
2 3 3 1 2 3
3 2 2 1 2 3
NA NA NA NA NA NA
NA 3 1 NA 2 1
现在删除只包含缺失观测值的行:
m[rowSums(is.na(m))<ncol(m),]
以下是结果:
1 1 NA 2 2 2
2 3 3 1 2 3
3 2 2 1 2 3
NA 3 1 NA 2 1
一种真正快速的方法是使用一点数学。假设您的数据框称为datf。
rsum <- rowSums(datf)
datf <- datf[rowSums != 44,] #11 * 4
c(4,4,4,4,4,4,4,4,4,3,5)
)。 - Joshua Ulrichset.seed(21)
m <- matrix(sample(1:6, 110, replace=TRUE), ncol=11)
missVal <- 4
m[4, ] <- rep(missVal, 11)
m <- m[ rowSums((m==missVal)) != NCOL(m), ]
m==missVal
返回一个由逻辑值(TRUE
/FALSE
)组成的矩阵。 rowSums
将TRUE
转换为1,将FALSE
转换为0,在这种情况下,当rowSums
返回11时,我们知道所有列都是4
。使用 data.table
实现内存效率。创建 is.na(x)
的解决方案会创建一个与原始数据集一样大的数据集,因此效率低下。
library(data.table)
DT <- as.data.table(m)
missing_value <- 4
missing <- as.data.table(setNames(as.list(rep(4, length(DT)), names(DT))
setkeyv(DT, names(DT))
setkey(missing, names(DT))
DT[-DT[(missing),which=T]]
这个解决方案和@JoshuaUlrich的解决方案在处理大量数据时都很快
set.seed(21)
m <- matrix(sample(1:6, 1100000, replace=TRUE), ncol=11)
missVal <- 4
missing_rows <- sample(100000, 53)
m[missing_rows, ] <- rep(missVal, 11)
DT <- as.data.table(m)
setkeyv(DT, names(DT))
missing <- setNames(as.list(rep(missVal, 11)), names(DT))
system.time({DT1 <- DT[-DT[missing,which=T]]})
## user system elapsed
## 0.02 0.00 0.01
system.time({m1 <- m[ rowSums((m==missVal)) != NCOL(m), ]})
## user system elapsed
## 0.02 0.02 0.03
T
/F
代替TRUE
/FALSE
时要小心,因为T
和F
可以被重新定义。 - Joshua Ulrich类似这样的代码应该可以解决问题(并且适用于矩阵和数据框):
ac<-matrix(c("4","4","4","4","4","4","4","3","3","4","4", rep("4", 11)), nrow=2, ncol=11, byrow=TRUE)
rowsToRemove<-which(apply(ac, 1, function(currow){
all(currow=="4")
}))
现在你可以简单地执行
newac<-ac[-rowsToRemove,]
str(head(foo))
命令,其中foo
是您的数据。 - joran