Подтвердить что ты не робот

Среднее количество элементов в списке data.frames

Предположим, что у меня есть список data.frames(равных строк и столбцов)

dat1=as.data.frame(matrix(rnorm(25),ncol=5))
dat2=as.data.frame(matrix(rnorm(25),ncol=5))
dat3=as.data.frame(matrix(rnorm(25),ncol=5))

all.dat<-list(dat1=dat1,dat2=dat2,dat3=dat3)

Как я могу вернуть один data.frame, который является средним значением (или суммой и т.д.) для каждого элемента в data.frames в списке (например, среднее значение первой строки и первого столбца из списков 1, 2, 3 и так далее)? Я попытался lapply и ldply в plyr, но они возвращают статистику для каждого data.frame в списке.

Изменить: по какой-то причине это было изменено как домашнее задание. Не то, чтобы это имело значение в любом случае, но это не вопрос домашней работы, я просто не знаю, почему я могу заставить это работать. Спасибо за понимание!

Edit2: для дальнейшего уточнения Я могу получить результаты с помощью циклов, но я надеялся, что есть способ (более простой и быстрый способ, поскольку данные, которые я использую, имеют data.frames, которые составляют 12 строк по 100 столбцов, и есть список из 1000+ этих данных кадры).

z<-matrix(0,nrow(all.dat$dat1),ncol(all.dat$dat1))

for(l in 1:nrow(all.dat$dat1)){
   for(m in 1:ncol(all.dat$dat1)){
      z[l,m]<-mean(unlist(lapply(all.dat, `[`, i =l, j = m)))
   }
}

с результатом средства:

> z
        [,1]        [,2]        [,3]        [,4]       [,5]
[1,] -0.64185488  0.06220447 -0.02153806  0.83567173  0.3978507
[2,] -0.27953054 -0.19567085  0.45718399 -0.02823715  0.4932950
[3,]  0.40506666  0.95157856  1.00017954  0.57434125 -0.5969884
[4,]  0.71972821 -0.29190645  0.16257478 -0.08897047  0.9703909
[5,] -0.05570302  0.62045662  0.93427522 -0.55295824  0.7064439

Мне было интересно, был ли менее неуклюжий и быстрый способ сделать это. Спасибо!

4b9b3361

Ответ 1

Вот один лайнер с plyr. Вы можете заменить mean любой другой функцией, которую вы хотите.

ans1 = aaply(laply(all.dat, as.matrix), c(2, 3), mean)

Ответ 2

У вас было бы легче изменить структуру данных, объединив три двухмерные матрицы в один трехмерный массив (используя библиотеку abind). Тогда решение более прямое использование apply и указание размеров на среднее значение.

EDIT:

Когда я ответил на вопрос, он был помечен homework, поэтому я просто дал подход. Оригинальный плакат удалил этот тег, поэтому я возьму его/ее по его/ее слову, что это не так.

library("abind")

all.matrix <- abind(all.dat, along=3)
apply(all.matrix, c(1,2), mean)

Ответ 3

Я дал один ответ, который использует совершенно другую структуру данных для достижения результата. В этом ответе напрямую используется структура данных (список фреймов данных). Я думаю, что он менее изящный, но все равно хотел его предоставить.

Reduce(`+`, all.dat) / length(all.dat)

Логика заключается в том, чтобы добавить кадры данных вместе по элементу (который + будет делать с кадрами данных), а затем делить на количество кадров данных. Использование Reduce необходимо, так как + может принимать только два аргумента за раз (и добавление ассоциативно).

Ответ 4

Другой подход, использующий только функции base для изменения структуры объекта:

listVec <- lapply(all.dat, c, recursive=TRUE)
m <- do.call(cbind, listVec)

Теперь вы можете рассчитать mean с помощью rowMeans или median с помощью apply:

means <- rowMeans(m)
medians <- apply(m, 1, median)

Ответ 5

Я бы взял несколько иной подход:

library(plyr)
tmp <- ldply(all.dat) # convert to df
tmp$counter <- 1:5 # 1:12 for your actual situation
ddply(tmp, .(counter), function(x) colMeans(x[2:ncol(x)]))

Ответ 6

Не могли бы вы просто использовать вложенные вызовы lapply()?

Это, как представляется, дает правильный результат на моей машине

mean.dat <- lapply(all.dat, function (x) lapply(x, mean, na.rm=TRUE))