Среднее значение элементов в списке 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

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


person ChrisC    schedule 04.10.2011    source источник
comment
Это не средство. Это медианы.   -  person Brandon Bertelsen    schedule 04.10.2011
comment
Спасибо что подметил это.   -  person ChrisC    schedule 04.10.2011


Ответы (6)


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

ans1 = aaply(laply(all.dat, as.matrix), c(2, 3), mean)
person Ramnath    schedule 05.10.2011
comment
почему c (2,3)? что это обозначает? - person nafrtiti; 23.04.2018
comment
Это способ доступа к массиву ... он в основном преобразует данные в 3-мерный массив, а затем извлекает из него значение столбца ... элегантно ... престиж - person Mario Fajardo; 28.05.2018

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

РЕДАКТИРОВАТЬ:

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

library("abind")

all.matrix <- abind(all.dat, along=3)
apply(all.matrix, c(1,2), mean)
person Brian Diggs    schedule 04.10.2011
comment
Я не знал, что такое абинд, я разберусь. Спасибо! - person ChrisC; 04.10.2011

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

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

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

person Brian Diggs    schedule 04.10.2011
comment
На самом деле это была стратегия, которую я изначально пробовал, но она работает только в том случае, если я пытаюсь получить средства или суммы, но я также хотел иметь возможность найти медиану. Думаю, лучшим вариантом будет изменение структуры данных. - person ChrisC; 04.10.2011
comment
Я не могу придумать, как приспособить это к медиане; Для медианы нужны все элементы сразу, а среднее значение может быть построено по два за раз. - person Brian Diggs; 04.10.2011
comment
Этот ответ лучше, чем stackoverflow.com/a/7651775/4907, когда список data.frame очень длинный. - person Michael Schneider; 16.06.2015
comment
Это самое чистое решение, однако оно не работает, когда есть символьный столбец (например, ключ, который одинаков в каждом списке). - person jzadra; 22.01.2019
comment
@jzadra Верно, но среднее значение вектора символьных строк все равно не определено. Там, где они будут просто ярлыками, data.frame может быть подмножеством, чтобы удалить их, а затем снова добавить набор. - person Brian Diggs; 23.01.2019

Другой подход, использующий только 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)
person Oscar Perpiñán    schedule 05.10.2011

Я бы выбрал немного другой подход:

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)]))
person Brandon Bertelsen    schedule 04.10.2011

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

Похоже, это дает правильный результат на моей машине

mean.dat <- lapply(all.dat, function (x) lapply(x, mean, na.rm=TRUE))
person richiemorrisroe    schedule 04.10.2011
comment
С помощью этого кода вы получаете среднее значение столбцов каждого data.frame. Вы получите тот же результат с lapply(all.dat, colMeans). - person Oscar Perpiñán; 05.10.2011