Replace missing values with column mean
我不确定如何遍历每列以将NA值替换为列均值。 当我尝试使用以下内容替换一列时,它会很好地工作。
1 | Column1[is.na(Column1)] <- round(mean(Column1, na.rm = TRUE)) |
循环列的代码不起作用:
1 2 3 | for(i in 1:ncol(data)){ data[i][is.na(data[i])] <- round(mean(data[i], na.rm = TRUE)) } |
值不会被替换。 有人可以帮我吗?
相对简单地修改您的代码即可解决此问题:
1 2 3 | for(i in 1:ncol(data)){ data[is.na(data[,i]), i] <- mean(data[,i], na.rm = TRUE) } |
如果
1 2 | library(zoo) na.aggregate(DF) |
添加:
仅使用R的基数定义一个函数,该函数针对一列执行此操作,然后应用于每个列:
1 2 | NA2mean <- function(x) replace(x, is.na(x), mean(x, na.rm = TRUE)) replace(DF, TRUE, lapply(DF, NA2mean)) |
如果可以覆盖输入,则可以用以下内容替换最后一行:
1 | DF[] <- lapply(DF, NA2mean) |
为了添加其他选择,使用@akrun的示例数据,我将执行以下操作:
1 2 3 4 5 | d1[] <- lapply(d1, function(x) { x[is.na(x)] <- mean(x, na.rm = TRUE) x }) d1 |
还有一个使用imputeTS软件包的快速解决方案:
1 2 | library(imputeTS) na_mean(yourDataFrame) |
可以使用
1 | d1[] <- lapply(d1, function(x) ifelse(is.na(x), mean(x, na.rm = TRUE), x)) |
与for循环相比,这实际上没有任何优势,尽管如果您也具有非数字列,则可能会更容易,在这种情况下
1 | d1[sapply(d1, is.numeric)] <- lapply(d1[sapply(d1, is.numeric)], function(x) ifelse(is.na(x), mean(x, na.rm = TRUE), x)) |
几乎一样容易。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | library(dplyr) set.seed(10) df <- data.frame(a = sample(c(NA, 1:3) , replace = TRUE, 10), b = sample(c(NA, 101:103), replace = TRUE, 10), c = sample(c(NA, 201:203), replace = TRUE, 10)) df #> a b c #> 1 2 102 203 #> 2 1 102 202 #> 3 1 NA 203 #> 4 2 102 201 #> 5 NA 101 201 #> 6 NA 101 202 #> 7 1 NA 203 #> 8 1 101 NA #> 9 2 101 203 #> 10 1 103 201 df %>% mutate_all(~ifelse(is.na(.x), mean(.x, na.rm = TRUE), .x)) #> a b c #> 1 2.000 102.000 203.0000 #> 2 1.000 102.000 202.0000 #> 3 1.000 101.625 203.0000 #> 4 2.000 102.000 201.0000 #> 5 1.375 101.000 201.0000 #> 6 1.375 101.000 202.0000 #> 7 1.000 101.625 203.0000 #> 8 1.000 101.000 202.1111 #> 9 2.000 101.000 203.0000 #> 10 1.000 103.000 201.0000 df %>% mutate_at(vars(a, b),~ifelse(is.na(.x), mean(.x, na.rm = TRUE), .x)) #> a b c #> 1 2.000 102.000 203 #> 2 1.000 102.000 202 #> 3 1.000 101.625 203 #> 4 2.000 102.000 201 #> 5 1.375 101.000 201 #> 6 1.375 101.000 202 #> 7 1.000 101.625 203 #> 8 1.000 101.000 NA #> 9 2.000 101.000 203 #> 10 1.000 103.000 201 |
您也可以尝试:
1 2 3 4 | cM <- colMeans(d1, na.rm=TRUE) indx <- which(is.na(d1), arr.ind=TRUE) d1[indx] <- cM[indx[,2]] d1 |
数据
1 2 | set.seed(42) d1 <- as.data.frame(matrix(sample(c(NA,0:5), 5*10, replace=TRUE), ncol=10)) |
简单地使用Zoo,它将简单地用列值的平均值替换所有NA值:
1 2 | library(zoo) na.aggregate(data) |
使用tidyr的replace_na的单线是
1 2 | library(tidyr) replace_na(mtcars,as.list(colMeans(mtcars,na.rm=T))) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # Lets say I have a dataframe , df as following - df <- data.frame(a=c(2,3,4,NA,5,NA),b=c(1,2,3,4,NA,NA)) # create a custom function fillNAwithMean <- function(x){ na_index <- which(is.na(x)) mean_x <- mean(x, na.rm=T) x[na_index] <- mean_x return(x) } (df <- apply(df,2,fillNAwithMean)) a b 2.0 1.0 3.0 2.0 4.0 3.0 3.5 4.0 5.0 2.5 3.5 2.5 |
与@Thomas指出的答案类似,
也可以使用R的
1 2 3 4 5 | for(i in 1:ncol(data)){ data[,i]=ifelse(is.na(data[,i]), ave(data[,i],FUN=function(y) mean(y, na.rm = TRUE)), data[,i]) } |
哪里,
测试逻辑条件
是-如果条件为True,则执行
否-否则当条件为False时
使用data.table包,您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | require(data.table) # data dt = copy(iris[ ,-5]) setDT(dt) dt[1:4, Sepal.Length := NA] # introduce NAs # replace NAs with mean (or whatever function you like) for (j in seq_along(names(dt))) { set(dt, i = which(is.na(dt[[j]])), j = j, value = mean(dt[[j]], na.rm = TRUE)) } |