Comment remplacer NA avec une moyenne de sous-ensemble dans R (imputer à plyr?)

StackOverflow https://stackoverflow.com/questions/9322773

  •  27-10-2019
  •  | 
  •  

Question

I ont une trame de données avec les longueurs et les largeurs des divers arthropodes des entrailles de la salamandre. Parce que certains tripes avaient des milliers de certains articles de proie, je ne mesure un sous-ensemble de chaque type de proie. Je veux maintenant remplacer chaque individu non mesuré par la longueur moyenne et la largeur de cette proie. Je veux garder la trame de données et juste ajouter des colonnes (length2, imputées largeur2). La principale raison est que chaque ligne a également des colonnes avec des données sur la date et le lieu de la salamandre ont été recueillies. Je pourrais remplir le NA avec une sélection aléatoire des individus mesurés mais pour les besoins du raisonnement, supposons que je veux juste remplacer chaque NA avec la moyenne.

Par exemple imaginer que j'ai un dataframe qui ressemble à quelque chose comme:

id    taxa        length  width
101   collembola  2.1     0.9
102   mite        0.9     0.7
103   mite        1.1     0.8
104   collembola  NA      NA
105   collembola  1.5     0.5
106   mite        NA      NA

En réalité, j'ai plusieurs colonnes et environ 25 taxons différents et un total de ~ 30.000 articles de proie au total. Il semble que le paquet plyr pourrait être idéal pour cela, mais je ne peux pas comprendre comment faire cela. Je ne suis pas très R ou la programmation avertis mais je suis en train d'apprendre.

Pas que je sache ce que je fais, mais je vais essayer de créer un petit jeu de données à jouer avec si elle aide.

exampleDF <- data.frame(id = seq(1:100), taxa = c(rep("collembola", 50), rep("mite", 25), 
rep("ant", 25)), length = c(rnorm(40, 1, 0.5), rep("NA", 10), rnorm(20, 0.8, 0.1), rep("NA", 
5), rnorm(20, 2.5, 0.5), rep("NA", 5)), width = c(rnorm(40, 0.5, 0.25), rep("NA", 10), 
rnorm(20, 0.3, 0.01), rep("NA", 5), rnorm(20, 1, 0.1), rep("NA", 5)))

Voici quelques choses que j'ai essayé (qui n'ont pas travaillé):

# mean imputation to recode NA in length and width with means 
  (could do random imputation but unnecessary here)
mean.imp <- function(x) { 
  missing <- is.na(x) 
  n.missing <-sum(missing) 
  x.obs <-a[!missing] 
  imputed <- x 
  imputed[missing] <- mean(x.obs) 
  return (imputed) 
  } 

mean.imp(exampleDF[exampleDF$taxa == "collembola", "length"])

n.taxa <- length(unique(exampleDF$taxa))
for(i in 1:n.taxa) {
  mean.imp(exampleDF[exampleDF$taxa == unique(exampleDF$taxa[i]), "length"])
} # no way to get back into dataframe in proper places, try plyr? 

une autre tentative:

imp.mean <- function(x) {
  a <- mean(x, na.rm = TRUE)
  return (ifelse (is.na(x) == TRUE , a, x)) 
 } # tried but not sure how to use this in ddply

Diet2 <- ddply(exampleDF, .(taxa), transform, length2 = function(x) {
  a <- mean(exampleDF$length, na.rm = TRUE)
  return (ifelse (is.na(exampleDF$length) == TRUE , a, exampleDF$length)) 
  })

Toutes les suggestions en utilisant plyr ou non?

Était-ce utile?

La solution

Pas ma propre technique je l'ai vu sur les planches un certain temps:

dat <- read.table(text = "id    taxa        length  width
101   collembola  2.1     0.9
102   mite        0.9     0.7
103   mite        1.1     0.8
104   collembola  NA      NA
105   collembola  1.5     0.5
106   mite        NA      NA", header=TRUE)


library(plyr)
impute.mean <- function(x) replace(x, is.na(x), mean(x, na.rm = TRUE))
dat2 <- ddply(dat, ~ taxa, transform, length = impute.mean(length),
     width = impute.mean(width))

dat2[order(dat2$id), ] #plyr orders by group so we have to reorder

Modifier Une approche de non plyr avec une boucle de for:

for (i in which(sapply(dat, is.numeric))) {
    for (j in which(is.na(dat[, i]))) {
        dat[j, i] <- mean(dat[dat[, "taxa"] == dat[j, "taxa"], i],  na.rm = TRUE)
    }
}

Modifier de nombreuses lunes plus tard ici est data.table & dplyr approche:

data.table

library(data.table)
setDT(dat)

dat[, length := impute.mean(length), by = taxa][,
    width := impute.mean(width), by = taxa]

dplyr

library(dplyr)

dat %>%
    group_by(taxa) %>%
    mutate(
        length = impute.mean(length),
        width = impute.mean(width)  
    )

Autres conseils

Avant de répondre à cela, je veux dire que suis un débutant dans R. Donc, s'il vous plaît laissez-moi savoir si vous vous sentez ma réponse est fausse.

Code:

DF[is.na(DF$length), "length"] <- mean(na.omit(telecom_original_1$length))

et appliquer la même pour la largeur.

DF signifie nom du data.frame.

Merci, Parthi

L'expansion de la solution de @Tyler Rinker, features sont les colonnes suppose à imputer. Dans ce cas features <- c('length', 'width'). Ensuite, en utilisant data.table la solution devient:

library(data.table)
setDT(dat)

dat[, (features) := lapply(.SD, impute.mean), by = taxa, .SDcols = features]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top