web-dev-qa-db-fra.com

Remplacer les valeurs manquantes par la moyenne de la colonne

Je ne suis pas sûr de savoir comment passer en boucle sur chaque colonne pour remplacer les valeurs de NA par la moyenne de colonne. Lorsque je tente de remplacer une colonne à l’aide de ce qui suit, cela fonctionne bien.

Column1[is.na(Column1)] <- round(mean(Column1, na.rm = TRUE))

Le code pour boucler sur les colonnes ne fonctionne pas:

for(i in 1:ncol(data)){
    data[i][is.na(data[i])] <- round(mean(data[i], na.rm = TRUE))
}

les valeurs ne sont pas remplacées. Quelqu'un pourrait m'aider avec ça?

31
Nikita

Une modification relativement simple de votre code devrait résoudre le problème:

for(i in 1:ncol(data)){
  data[is.na(data[,i]), i] <- mean(data[,i], na.rm = TRUE)
}
50
Thomas

Si DF est votre cadre de données de colonnes numériques:

library(Zoo)
na.aggregate(DF)

AJOUTÉE:

En utilisant uniquement la base de R, définissez une fonction qui le fait pour une colonne, puis lapply à chaque colonne:

NA2mean <- function(x) replace(x, is.na(x), mean(x, na.rm = TRUE))
replace(DF, TRUE, lapply(DF, NA2mean))

La dernière ligne peut être remplacée par la suivante si vous pouvez remplacer l’entrée:

DF[] <- lapply(DF, NA2mean)
39
G. Grothendieck

Pour ajouter aux alternatives, en utilisant les exemples de données de @ akrun, je procéderais comme suit:

d1[] <- lapply(d1, function(x) { 
  x[is.na(x)] <- mean(x, na.rm = TRUE)
  x
})
d1
10

Vous pouvez aussi essayer:

 cM <- colMeans(d1, na.rm=TRUE)
 indx <- which(is.na(d1), arr.ind=TRUE)
 d1[indx] <- cM[indx[,2]]
 d1  

les données

set.seed(42)
d1 <- as.data.frame(matrix(sample(c(NA,0:5), 5*10, replace=TRUE), ncol=10))
5
akrun

lapply peut être utilisé à la place d'une boucle for.

d1[] <- lapply(d1, function(x) ifelse(is.na(x), mean(x, na.rm = TRUE), x))

Cela n’a aucun avantage par rapport à la boucle for, bien que ce soit peut-être plus facile si vous avez également des colonnes non numériques, auquel cas

d1[sapply(d1, is.numeric)] <- lapply(d1[sapply(d1, is.numeric)], function(x) ifelse(is.na(x), mean(x, na.rm = TRUE), x))

est presque aussi facile.

4
Ista
# 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
2
shekhar

Similaire à la réponse indiquée par @Thomas, Ceci peut également être effectué à l'aide de la méthode ifelse() de R:

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

où, Les arguments à ifelse(TEST, YES , NO) sont: -

TEST- condition logique à vérifier

OUI- exécuté si la condition est vraie

NO- sinon lorsque la condition est fausse

et ave(x, ..., FUN = mean) est la méthode de R utilisée pour calculer les moyennes de sous-ensembles de x []

1
Aseem Yadav

Il existe aussi une solution rapide en utilisant le paquet imputeTS :

library(imputeTS)
na.mean(yourDataFrame)
1
stats0007

dplyr 's mutate_all ou mutate_at pourrait être utile ici:

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
0
zack