nalzok
nalzok

Reputation: 16107

Applying a function across nested list

Say, I have the following list

raw <- list(list(1:2, 2:3, 3:4), list(4:5, 5:6, 6:7), list(7:8, 8:9, 9:10))

I would like to find the mean of the corresponding entries of the out-most list. The expected output would be something like

[[1]]
[1] 4 5

[[2]]
[1] 5 6

[[3]]
[1] 6 7

This is because the mean of 1:2, 4:5, and 7:8 would be 4:5.

I have been experimenting with stuff like lapply(raw, function(x) lapply(x, mean)), but apparently it doesn't return the desired output.

Upvotes: 1

Views: 64

Answers (3)

d.b
d.b

Reputation: 32548

1

n = length(raw[[1]])
lapply(1:n, function(i){
    d = do.call(rbind, lapply(seq_along(raw), function(j){
        raw[[j]][[i]]
    }))
    apply(d, 2, mean)
})
#[[1]]
#[1] 4 5

#[[2]]
#[1] 5 6

#[[3]]
#[1] 6 7

2

aggregate(. ~ ind, do.call(rbind, lapply(raw, function(x)
    data.frame(cbind(do.call(rbind, x), ind = seq_along(x))))), mean)
#  ind V1 V2
#1   1  4  5
#2   2  5  6
#3   3  6  7

Upvotes: 2

jay.sf
jay.sf

Reputation: 72673

You could put the thing into an array and take the cell medians (I suppose you want these instead of means).

A <- array(matrix(unlist(raw), 2, byrow=FALSE), dim=c(2, 3, 3))
v.mds <- t(apply(A, 1:2, median))
lapply(1:3, function(x) v.mds[x, ])
#   [[1]]
# [1] 4 5
# 
#   [[2]]
# [1] 5 6
# 
#   [[3]]
# [1] 6 7

Generalized like so:

A <- array(matrix(unlist(raw), length(el(el(raw))), byrow=0), 
           dim=c(length(el(el(raw))), el(lengths(raw)), length(raw)))
v.mds <- t(apply(A, 1:2, median))
lapply(1:nrow(v.mds), function(x) v.means[x, ])

Upvotes: 1

MrFlick
MrFlick

Reputation: 206197

This is pretty ugly, but we can use mapply to iterate over the lists but we need to expand the list into parameters via do.call

do.call("mapply", c(function(...) rowMeans(data.frame(...)), raw, SIMPLIFY=FALSE))

You can make this prettier using the purrr package

purrr::pmap(raw, ~rowMeans(data.frame(...)))

Upvotes: 2

Related Questions