Element-wise mean in R
Asked Answered
U

4

39

In R, I have two vectors:

a <- c(1, 2, 3, 4)
b <- c(NA, 6, 7, 8)

How do I find the element-wise mean of the two vectors, removing NA, without a loop? i.e. I want to get the vector of

(1, 4, 5, 6)

I know the function mean(), I know the argument na.rm = 1. But I don't know how to put things together. To be sure, in reality I have thousands of vectors with NA appearing at various places, so any dimension-dependent solution wouldn't work. Thanks.

Unsay answered 16/8, 2010 at 21:20 Comment(0)
P
45

how about:

rowMeans(cbind(a, b), na.rm=TRUE)

or

colMeans(rbind(a, b), na.rm=TRUE)
Pretender answered 16/8, 2010 at 21:27 Comment(4)
Ok, those are cool. But to get what I wanted you still need to add na.rm = 1, and that solves my problem. Thx.Unsay
I just added the na.rm arguments.Pretender
colSums and rowSums also exist @Zhang18, FYI.Tema
The generalisation of this to higher dimension arrays is something like: apply(abind(a, b, along=0), c(2,3,4), mean, na.rm=TRUE) (if a and b are 3 dimensional to start with).Veracruz
S
4

I'm not exactly sure what you are asking for, but does

apply(rbind(a,b),2,mean,na.rm = TRUE)

do what you want?

Spongin answered 16/8, 2010 at 21:33 Comment(1)
The Details section of ?colMeans and ?rowMeans explains that these functions are much faster than apply with fun = mean as they are implemented for speed.Pretender
W
2

A tidyverse solution usign purrr:

library(purrr)
a <- c(1, 2, 3, 4)
b <- c(NA, 6, 7, 8)

# expected:
c(1, 4, 5, 6) 
#> [1] 1 4 5 6

# actual:
map2_dbl(a,b, ~mean(c(.x,.y), na.rm=T)) # actual
#> [1] 1 4 5 6

And for any number of vectors:

>  pmap_dbl(list(a,b, a, b), compose(partial(mean, na.rm = T), c))
 [1] 1 4 5 6
Witherite answered 14/10, 2019 at 10:15 Comment(0)
A
0

Another option is collapse::fmean, which defaults to column-wise means on matrices and na.rm = TRUE:

fmean(rbind(a, b))
#[1] 1 4 5 6

Benchmark

Vectors a and b (length = 4):

microbenchmark::microbenchmark(
  collapse = fmean(rbind(a, b)),
  rowMeans = rowMeans(cbind(a, b), na.rm=TRUE),
  colMeans = colMeans(rbind(a, b), na.rm=TRUE),
  purrr = purrr::map2_dbl(a,b, ~mean(c(.x,.y), na.rm=T)),
  apply = apply(rbind(a,b),2,mean,na.rm = TRUE)
)

# Unit: microseconds
#      expr    min       lq      mean   median       uq      max neval
#  collapse  6.501   7.9020  10.72705   9.7010  10.8010   56.101   100
#  rowMeans  4.601   6.0505   9.21504   7.8010   9.4515   28.102   100
#  colMeans  4.700   5.7010   7.76410   6.8515   8.2015   27.301   100
#     purrr 94.101 104.4505 140.36694 108.8010 121.9510 2120.901   100
#     apply 50.301  55.1010  65.37305  59.9005  65.6510  156.700   100

Large vectors (size 1e6):

a = sample(1e6)
b = sample(1e6)

# Unit: milliseconds
#      expr       min        lq     mean    median       uq     max neval
#  collapse  8.384401  9.621752 13.02568 10.160101 18.83060 34.2746   100
#  rowMeans 18.504201 21.513251 27.88083 23.509051 31.28925 94.2124   100
#  colMeans  8.117601  9.344551 12.69392  9.897702 12.50430 54.1703   100
Ant answered 5/5, 2023 at 14:2 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.