我想替换数据帧列中的缺失值。我写了以下代码
MedianImpute <- function(data=data)
{
for(i in 1:ncol(data))
{
if(class(data[,i]) %in% c("numeric","integer"))
{
if(sum(is.na(data[,i])))
{
data[is.na(data[,i]),i] <-
median(data[,i],na.rm = TRUE)
}
}
}
return(data)
}
这将返回数据帧,其中NAs由列中位数替换。 我不想使用for循环,如何使用R?
中的任何apply函数得到相同的结果答案 0 :(得分:3)
您可以使用apply
在所有列中应用函数
dat<-data.frame(c1=c(1,2,3,NA),c2=c(10, NA, 20, 30))
apply(dat, 2, function(x) ifelse(is.na(x), median(x, na.rm=T), x))
稍快一点
imputeMedianv3<-function(x) apply(x, 2, function(x){x[is.na(x)]<-median(x, na.rm=T); x})
我确定您所寻找的是性能,有人会提供数据表解决方案(不幸的是我不熟悉该软件包,因此无法自行完成)。
答案 1 :(得分:3)
这实际上是一个微妙的问题,所以值得一些讨论(IMO)。您有一个data frame
,并且只想为数字列输入中位数,结果当然是数据框。
apply(...)
函数将首先强制它的矩阵参数。由于矩阵中的所有元素必须是相同的数据类型,如果原始df中有任何字符或因子列,,当传递给{{时,整个矩阵将被强制转换为char 1}}。
apply(...)
# 1st column of df is a factor
df <- data.frame(a=letters[1:5],x=sample(1:5,5),y=runif(5))
df[3,]$x <- NA
df[5,]$y <- NA
df
# a x y
# 1 a 5 0.5235779
# 2 b 3 0.2142011
# 3 c NA 0.8886608
# 4 d 4 0.4952574
# 5 e 1 NA
apply(df,2,function(x) {
if(is.numeric(x)) ifelse(is.na(x),median(x,na.rm=T),x) else x})
# a x y
# [1,] "a" " 5" "0.5235779"
# [2,] "b" " 3" "0.2142011"
# [3,] "c" NA "0.8886608"
# [4,] "d" " 4" "0.4952574"
# [5,] "e" " 1" NA
会将sapply(df,FUN=f)
的列分别传递给函数df
,但是,结果将是矩阵。因此,例如,f(...)
中的任何因子都将被强制转换为整数。
df
所以在这里sapply(df,function(x) {
if(is.numeric(x)) ifelse(is.na(x),median(x,na.rm=T),x) else x})
# a x y
# [1,] 1 5.0 0.5235779
# [2,] 2 3.0 0.2142011
# [3,] 3 3.5 0.8886608
# [4,] 4 4.0 0.4952574
# [5,] 5 1.0 0.5094176
和df$x
是正确的,但看看df$y
发生了什么:通过返回因子级别将因子强制转换为数字 - 而不是你想要的!
df$a
将返回一个列表,然后可以将其转换为数据帧。这种方法可以为您提供所需的结果:
lapply(df,FUN=F)
我认为这是否比使用循环更好有争议......