我不知道如何在每列上循环,用列平均值替换NA值。当我试图用以下内容替换一列时,效果很好。
Column1[is.na(Column1)] <- round(mean(Column1, na.rm = TRUE))
在列上循环的代码不起作用:
for(i in 1:ncol(data)){
data[i][is.na(data[i])] <- round(mean(data[i], na.rm = TRUE))
}
这些值不会被替换。有人能帮我做这个吗?
一个相对简单的代码修改应该可以解决这个问题:
for(i in 1:ncol(data)){
data[is.na(data[,i]), i] <- mean(data[,i], na.rm = TRUE)
}
如果DF
是数字列的数据帧:
library(zoo)
na.aggregate(DF)
添加:
仅使用R的基来定义一个函数,该函数对一列执行此操作,然后覆盖到每列:
NA2mean <- function(x) replace(x, is.na(x), mean(x, na.rm = TRUE))
replace(DF, TRUE, lapply(DF, NA2mean))
如果可以覆盖输入,最后一行可以替换为以下内容:
DF[] <- lapply(DF, NA2mean)
dplyr
的mutate_all
或mutate_at
在这里可能很有用:
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
使用imputeTS包也有快速解决方案:
library(imputeTS)
na_mean(yourDataFrame)
要添加到备选方案中,使用@akrun的样本数据,我将执行以下操作:
d1[] <- lapply(d1, function(x) {
x[is.na(x)] <- mean(x, na.rm = TRUE)
x
})
d1
lapply
可以代替for
循环使用。
d1[] <- lapply(d1, function(x) ifelse(is.na(x), mean(x, na.rm = TRUE), x))
与for循环相比,这并没有任何优势,但如果您也有非数字列,在这种情况下可能会更容易
d1[sapply(d1, is.numeric)] <- lapply(d1[sapply(d1, is.numeric)], function(x) ifelse(is.na(x), mean(x, na.rm = TRUE), x))
几乎同样容易。
使用tidyr的replace_na的一行是
library(tidyr)
replace_na(mtcars,as.list(colMeans(mtcars,na.rm=T)))
如果您的df
中有非数字列,那么这需要比一行多做一点工作。
mean_to_fill <- select_if(ungroup(df), is.numeric) %>%
colMeans(na.rm=T)
bind_cols(select(df, group1, group2, group3),
select_if(ungroup(df), is.numeric) %>%
tidyr::replace_na(as.list(mean_to_fill))
)
您也可以尝试:
cM <- colMeans(d1, na.rm=TRUE)
indx <- which(is.na(d1), arr.ind=TRUE)
d1[indx] <- cM[indx[,2]]
d1
数据
set.seed(42)
d1 <- as.data.frame(matrix(sample(c(NA,0:5), 5*10, replace=TRUE), ncol=10))
简单地使用Zoo,它将简单地用列值的平均值替换所有NA值:
library(zoo)
na.aggregate(data)
# 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()
方法来完成
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 ,则执行
否-否则当条件为假时
CCD_ 10是R中用于计算x[]的子集的平均值的方法
使用data.table包,您可以使用set()
函数并在列上循环,并用您选择的聚合或值替换NA
或任何您喜欢的值(此处:均值):
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))
}
除了Denis答案,您还可以直接使用dplyr来计算平均值。如果在要选择的列中添加前缀,则可以使用contains或ends/starts_with():
df <- df%>%
mutate_at(vars(starts_with("prefix_")), ####Select vars starting with "prefix_"
~replace_na(.x, mean(.x, na.rm = TRUE))) #### replace na with mean
R的tidyr
包有一个专门用于此目的的功能:replace_na
meanvals <- as.list(colMeans(data, na.rm = TRUE))
data <- replace_na(data, meanvals)