Reputation: 159
I have a list with the following structure:
> str(test)
List of 5
$ :List of 2
..$ : num [1:4] 0.0544 0.0839 0.0486 0.043
..$ : num [1:4] 0.0799 0.2434 0.0373 0.2166
$ :List of 2
..$ : num [1:6] 0.938 1.047 1.022 0.689 0.39 ...
..$ : num [1:6] 0.871 0.25 0.824 0.664 0.481 ...
$ :List of 2
..$ : num [1:4] 0.000598 0.000923 0.000535 0.000473
..$ : num [1:4] 0.001039 0.003164 0.000485 0.002816
$ :List of 2
..$ : num [1:6] 0.01032 0.01152 0.01124 0.00758 0.00429 ...
..$ : num [1:6] 0.01133 0.00325 0.01071 0.00864 0.00625 ...
$ :List of 2
..$ : num -0.659
..$ : num -0.962
I want to compute the mean of each entry, i.e. for the first entry I want:
x <- mean(c(0.0544, 0.0839, 0.0486, 0.043))
y <- mean(c(0.0799, 0.2434, 0.0373, 0.2166))
And finally the mean of those two results = mean(c(x,y).
What is the most efficient way to do this?
Upvotes: 3
Views: 5707
Reputation: 28441
You can also use modify_depth
function from the purrr
package. Take example posted by @ngm
library(purrr)
set.seed(1)
foo <- list(list(runif(4), runif(4)),
list(runif(6), runif(6)))
modify_depth(foo, 2, mean)
#> [[1]]
#> [[1]][[1]]
#> [1] 0.5296734
#>
#> [[1]][[2]]
#> [1] 0.6763862
#>
#>
#> [[2]]
#> [[2]][[1]]
#> [1] 0.3574264
#>
#> [[2]][[2]]
#> [1] 0.6890909
Edit: to calculate the mean of all elements in the 1st level of that list
modify_depth(foo, 2, mean) %>%
map(flatten_dbl) %>%
map_dbl(mean)
modify_depth(foo, 2, mean) %>%
simplify_all() %>%
map_dbl(mean)
[1] 0.60303 0.52326
Created on 2018-04-20 by the reprex package (v0.2.0).
Upvotes: 1
Reputation: 2589
Sample data - one (parent) list of (child) lists.
set.seed(1)
foo <- list(
list(runif(4),runif(4)),
list(runif(6),runif(6))
)
#> [[1]]
#> [[1]][[1]]
#> [1] 0.2655087 0.3721239 0.5728534 0.9082078
#>
#> [[1]][[2]]
#> [1] 0.2016819 0.8983897 0.9446753 0.6607978
#>
#>
#> [[2]]
#> [[2]][[1]]
#> [1] 0.62911404 0.06178627 0.20597457 0.17655675 0.68702285 0.38410372
#>
#> [[2]][[2]]
#> [1] 0.7698414 0.4976992 0.7176185 0.9919061 0.3800352 0.7774452
Get the means of each child list:
foo_means <- lapply(foo, lapply, mean)
#> [[1]]
#> [[1]][[1]]
#> [1] 0.5296734
#>
#> [[1]][[2]]
#> [1] 0.6763862
#>
#>
#> [[2]]
#> [[2]][[1]]
#> [1] 0.3574264
#>
#> [[2]][[2]]
#> [1] 0.6890909
To get the average of (child) averages for each (parent) list element:
lapply(foo_means, function(x) mean(unlist(x)))
#> [[1]]
#> [1] 0.6030298
#>
#> [[2]]
#> [1] 0.5232587
Upvotes: 4
Reputation: 14370
The first question appears to be a perfect use for rapply
. Using the same sample data as provided above in @ngm's answer, you can do:
foo2 <- rapply(foo, mean, how = "replace")
foo2
#[[1]]
#[[1]][[1]]
#[1] 0.5296734
#
#[[1]][[2]]
#[1] 0.6763862
#
#
#[[2]]
#[[2]][[1]]
#[1] 0.3574264
#
#[[2]][[2]]
#[1] 0.6890909
Upvotes: 3
Reputation: 4648
This has been answered many times. It is as simple as
mean(unlist(lapply(mylist,sapply,mean)))
Follow this link.
Grouping functions (tapply, by, aggregate) and the *apply family
Upvotes: 1
Reputation: 3629
Since the elements of your list are also lists, then use some nested lapply
's to get the means of each list.
lapply(test, function(x) lapply(x, mean))
If you like a matrix as an output, you can do
sapply(test, function(x) sapply(x, mean))
With the sapply
, you can get the means of each pair with
colMeans(sapply(test, function(x) sapply(x, mean, na.rm = TRUE)))
Upvotes: 1