关于r:用列均值替换缺失值

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)
}


如果DF是数字列的数据框:

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)


可以使用lapply代替for循环。

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))

几乎一样容易。


dplyrmutate_allmutate_at在这里可能有用:

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的ifelse()方法完成此操作:

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])
}

哪里,
ifelse(TEST, YES , NO)的参数为:-

测试逻辑条件

是-如果条件为True,则执行

否-否则当条件为False时

ave(x, ..., FUN = mean)是R中的方法,用于计算x []的子集的平均值


使用data.table包,您可以使用set()函数并在列上循环,并用您选择的集合或值替换NA或您喜欢的任何内容(在这里:平均值):

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))
}