2012-02-17 15 views
12

Mam ramkę danych o długościach i szerokościach różnych stawonogów z wnętrzności salamander. Ponieważ niektóre flaki miały tysiące określonych przedmiotów zdobycznych, mierzyłem tylko podzbiór każdego rodzaju zdobyczy. Chcę teraz zastąpić każdą niezmierzoną osobę średnim długością i szerokością dla tej ofiary. Chcę zachować ramkę danych i po prostu dodać imputowane kolumny (length2, width2). Głównym powodem jest to, że każdy wiersz zawiera również kolumny z danymi o dacie i lokalizacji salamandry. Mogłem wypełnić NA z losowym wyborem mierzonych osobników, ale ze względu na argument, załóżmy, że chcę tylko zastąpić każdą NA średnią.Jak zastąpić NA ze średnią przez podzbiór w R (imporować za pomocą plyr?)

Na przykład wyobrazić Mam dataframe, który wygląda mniej więcej tak:

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 

W rzeczywistości mam więcej kolumn i około 25 różnych taksonów i łącznie ~ 30,000 pozycji ofiary w całości. Wygląda na to, że pakiet plyr może być idealny do tego, ale nie mogę pojąć, jak to zrobić. Nie jestem zbyt dobrym programistą lub programistą, ale próbuję się uczyć.

Nie wiem, co robię, ale postaram się utworzyć mały zestaw danych do zabawy, jeśli to pomoże.

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

Oto kilka rzeczy próbowałem (które wcześniej nie pracowały):

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

kolejna próba:

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

jakieś sugestie używając plyr czy nie?

+7

Powinieneś rozważyć pakowanie * myszy * dla wartości imputowanych. –

+1

Pakiet 'mi' jest również całkiem niezły. "Amelia" jest znacznie szybsza niż "myszy" lub "mi", ale opiera się na zmiennych, które są wielowymiarowe normalne – richiemorrisroe

Odpowiedz

37

Nie moja własna technika Widziałem go na deskach jakiś czas temu:

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 

Edit Non podejście plyr z for pętli:

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

Edytuj wiele księżyców późniejszym tutaj jest data.table dplyr ap miałaby znajdować:

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

@djhocking Dziękujemy Hadley dowiedziałem się skąd to ukradłem: [(LINK)] (http: // www.mail-archive.com/[email protected]/msg58289.html) –

2

Zanim odpowiemy na to, chcę powiedzieć, że jestem początkujący w R. Stąd, proszę daj mi znać, jeśli uważasz, że moja odpowiedź jest błędna.

Kod:

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

i stosować takie same dla szerokości.

DF oznacza nazwę data.frame.

Dzięki, Parthi

0

rozwijając rozwiązania @Tyler Rinker jest, załóżmy features są kolumny przypisać. W tym przypadku features <- c('length', 'width'). Następnie za pomocą data.table rozwiązanie staje się:

library(data.table) 
setDT(dat) 

dat[, (features) := lapply(.SD, impute.mean), by = taxa, .SDcols = features] 
Powiązane problemy