I have a list of lists with the following structure:
> mylist <- list(list(a=as.numeric(1:3), b=as.numeric(4:6)),
list(a=as.numeric(6:8), b=as.numeric(7:9)))
> str(mylist)
List of 2
$ :List of 2
..$ a: num [1:3] 1 2 3
..$ b: num [1:3] 4 5 6
$ :List of 2
..$ a: num [1:3] 6 7 8
..$ b: num [1:3] 7 8 9
I would like to get the element-wise mean between the vectors a
and b
of mylist
. For the vector a
, the result would be this:
> a
[1] 3.5 4.5 5.5
I know the functions lapply
, rbind
and colMeans
but I can't solve the problem with them. How can I achieve what I need?
Here's one approach that uses melt
and dcast
from "reshape2".
library(reshape2)
## "melt" your `list` into a long `data.frame`
x <- melt(mylist)
## add a "time" variable to let things line up correctly
## L1 and L2 are created by `melt`
## L1 tells us the list position (1 or 2)
## L2 us the sub-list position (or name)
x$time <- with(x, ave(rep(1, nrow(x)), L1, L2, FUN = seq_along))
## calculate whatever aggregation you feel in the mood for
dcast(x, L2 ~ time, value.var="value", fun.aggregate=mean)
# L2 1 2 3
# 1 a 3.5 4.5 5.5
# 2 b 5.5 6.5 7.5
Here's an approach in base R:
x <- unlist(mylist)
c(by(x, names(x), mean))
# a1 a2 a3 b1 b2 b3
# 3.5 4.5 5.5 5.5 6.5 7.5
Updated : Better yet...sapply(mylist, unlist)
actually gives us a nice matrix to apply rowMeans
over.
> rowMeans(sapply(mylist, unlist))
# a1 a2 a3 b1 b2 b3
# 3.5 4.5 5.5 5.5 6.5 7.5
Original :
Another lapply
method, with an sapply
thrown in there.
> lapply(1:2, function(i) rowMeans(sapply(mylist, "[[", i)) )
# [[1]]
# [1] 3.5 4.5 5.5
#
# [[2]]
# [1] 5.5 6.5 7.5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With