Domanda

Ho una dataframe con le lunghezze e larghezze di vari artropodi dalle viscere del salamandre. Poiché alcuni budella avevano migliaia di alcune prede, ho misurato solo un sottoinsieme di ogni tipo preda. Ora voglio sostituire ogni individuo non misurato con la lunghezza e la larghezza media per quella preda. Voglio mantenere il dataframe e basta aggiungere colonne imputati (length2, width2). La ragione principale è che ogni riga ha anche colonne con i dati relativi alla data e luogo la salamandra è stata raccolta. Potrei riempire il NA con una selezione casuale di individui misurati, ma per amor di discussione supponiamo voglio solo sostituire ogni NA con la media.

Per esempio immaginare ho un dataframe che sembra qualcosa di simile:

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

In realtà ho più colonne e circa 25 diversi taxa e un totale di circa 30.000 prede in totale. Sembra che il pacchetto plyr potrebbe essere l'ideale per questo, ma non riesco proprio a capire come fare questo. Io non sono molto esperto di R o di programmazione, ma sto cercando di imparare.

Non che io sappia quello che sto facendo, ma cercherò di creare un piccolo set di dati di giocare con se aiuta.

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

Qui ci sono alcune cose che ho provato (che non hanno funzionato):

# 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? 

un altro tentativo:

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

Qualche suggerimento utilizzando plyr o no?

È stato utile?

Soluzione

Non la mia tecnica che ho visto sulle tavole un po 'indietro:

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

Modifica un approccio non plyr con un ciclo 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)
    }
}

Modifica molte lune più tardi ecco un data.table e dplyr approccio:

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

Altri suggerimenti

Prima di rispondere a questo, voglio dire che sono un principiante in R. Quindi, per favore fatemi sapere se si sente la mia risposta è sbagliata.

Codice:

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

e applicare la stessa per la larghezza.

DF sta per il nome del data.frame.

Grazie, Parthi

Ampliando la soluzione di @Tyler Rinker, features supponiamo che sono le colonne imputare. In questo caso features <- c('length', 'width'). Quindi, utilizzando data.table la soluzione diventa:

library(data.table)
setDT(dat)

dat[, (features) := lapply(.SD, impute.mean), by = taxa, .SDcols = features]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top