2011-08-12 14 views
5

Mam listę identycznie posortowanych ramek danych. Bardziej szczegółowe są przypisane nam dane, które otrzymuję po wykonaniu wielu imputacji przy pomocy pakietu AmeliaII. Teraz chcę utworzyć nową ramkę danych, która ma identyczną strukturę, ale zawiera wartości średnie komórek obliczone na podstawie ramek danych.Oblicz statystyki (np. Średnie) w komórkach identycznych ramek danych.

Sposób, w jaki to osiągnąć w tej chwili jest następujący:

## do the Amelia run ------------------------------------------------------------ 

a.out <- amelia(merged, m=5, ts="Year", cs ="GEO",polytime=1) 

## Calculate the output statistics ---------------------------------------------- 
left.side <- a.out$imputations[[1]][,1:2] 
a.out.ncol <- ncol(a.out$imputations[[1]]) 

a <- a.out$imputations[[1]][,3:a.out.ncol] 
b <- a.out$imputations[[2]][,3:a.out.ncol] 
c <- a.out$imputations[[3]][,3:a.out.ncol] 
d <- a.out$imputations[[4]][,3:a.out.ncol] 
e <- a.out$imputations[[5]][,3:a.out.ncol] 

# Calculate the Mean of the matrices 
mean.right <- apply(abind(a,b,c,d,e,f,g,h,i,j,along=3),c(1,2),mean) 

# recombine factors with values 
mean <- cbind(left.side,mean.right) 

Przypuszczam, że jest to znacznie lepszy sposób to zrobić za pomocą zastosowania, plyr lub podobnego, ale jako R Newbie I jestem tu trochę zagubiony. Czy masz jakieś sugestie, jak to zrobić?

Odpowiedz

4

Oto alternatywna podejście używając Reduce i plyr::llply

dfr1 <- data.frame(a = c(1,2.5,3), b = c(9.0,9,9), c = letters[1:3]) 
dfr2 <- data.frame(a = c(5,2,5), b = c(6,5,4), c = letters[1:3]) 

tst = list(dfr1, dfr2) 

require(plyr) 
tst2 = llply(tst, function(df) df[,sapply(df, is.numeric)]) # strip out non-numeric cols 
ans = Reduce("+", tst2)/length(tst2) 

edytować. Możesz znacznie uprościć swój kod i osiągnąć to, co chcesz w 5 liniach kodu R. Oto przykład użycia pakietu Amelia.

library(Amelia) 
data(africa) 

# carry out imputations 
a.out  = amelia(x = africa, cs = "country", ts = "year", logs = "gdp_pc") 

# extract numeric columns from each element of a.out$impuations 
tst2  = llply(a.out$imputations, function(df) df[,sapply(df, is.numeric)]) 

# sum them up and divide by length to get mean 
mean.right = Reduce("+", tst2)/length(tst2) 

# compute fixed columns and cbind with mean.right 
left.side = a.out$imputations[[1]][1:2] 
mean0  = cbind(left.side,mean.right) 
4

Jeśli dobrze rozumiem Twoje pytanie, to należy Ci długą drogę:

#set up some data: 
dfr1<-data.frame(a=c(1,2.5,3), b=c(9.0,9,9)) 
dfr2<-data.frame(a=c(5,2,5), b=c(6,5,4)) 
tst<-list(dfr1, dfr2) 
#since all variables are numerical, use a threedimensional array 
tst2<-array(do.call(c, lapply(tst, unlist)), dim=c(nrow(tst[[1]]), ncol(tst[[1]]), length(tst))) 
#To see where you're at: 
tst2 
#rowMeans for a threedimensional array and dims=2 does the mean over the last dimension 
result<-data.frame(rowMeans(tst2, dims=2)) 
rownames(result)<-rownames(tst[[1]]) 
colnames(result)<-colnames(tst[[1]]) 
#display the full result 
result 

HTH.

+0

Dzięki, że tak naprawdę zajmuje mi to dużo czasu. Jednak w przeciwieństwie do twojego rozwiązania, moje ramki danych są nie tylko numeryczne, ale mają dwie kolumny "współczynników", które musiałem "rozebrać" przed użyciem tablicy. Gdybyś znał rozwiązanie, które działa również na "mieszanych" ramach danych, to dostałbym "całą drogę". Ale, jak powiedziano wcześniej, twoje rozwiązanie jest zdecydowanie bardziej zwięzłe niż to, którego używałem wcześniej. – Tungurahua

+0

Jeśli dobrze pamiętam, podane przeze mnie rozwiązanie, które udostępniłem, będzie nadal działało: czynniki będą wymuszane na liczbach, a średnia z nich będzie brana (co można bezpiecznie zignorować, ponieważ jest to w większości bezcelowe). –

1

Po wielu próbach znalazłem dość szybki sposób obliczania wartości komórek w wielu ramkach danych.

# First create an empty data frame for storing the average imputed values. This 
# data frame will have the same dimensions of the original one 

imp.df <- df 

# Then create an array with the first two dimensions of the original data frame and 
# the third dimension given by the number of imputations 

a <- array(NA, dim=c(nrow(imp.df), ncol(imp.df), length(a.out$imputations))) 

# Then copy each imputation in each "slice" of the array 

for (z in 1:length(a.out$imputations)) { 
a[,,z] <- as.matrix(a.out$imputations[[z]]) 
} 

# Finally, for each cell, replace the actual value with the mean across all 
# "slices" in the array 

for (i in 1:dim(a)[1]) { 
    for (j in 1:dim(a)[2]) { 
imp.df[i, j] <- mean(as.numeric(a[i, j,])) 
    }} 
Powiązane problemy