1

I would like to sum 5 to each element of an array (not through all dimensions) without using a loop for. As the result, I want to get an array with the exact same dimensions, but each element should have 5 added to it. I tried using the sum and the apply functions, but I either get the sum of each of the elements (one number), or this error message:

Error in apply(b[, , , 2], 5, FUN = sum, na.rm = T) : 
  'MARGIN' does not match dim(X)

I need to have na.rm = T, because there are a lot of NA in my dataset, so I want to get NA + 5 = 5

Here is an example where I'm trying to sum 5 to all dimensions but to [,,,1] :

b <- array(seq(1,48,1), dim = c(4,2,3,2))
b[4,2,3,2] <- NA

I tried:


sum(b[,,,2], 5, na.rm = T)

I was expecting to get as an answer:

(a <- array(c(seq(1,24,1),seq(25,47,1)+5, 5), dim = c(4,2,3,2)))

2 Answers2

3

R by default supports adding to matricies and arrays. You can just use the + operator to add a value to each element of a vector/matrix/array. Since you only want to affect parts of that array, just use square brackets to subset the parts you want to affect:

b[,,,2] <- b[,,,2] + 5

table(b==a, useNA='always')

TRUE <NA> 
  47    1 

You have NA values in your array. In R, by default, operations involving an NA return NA. So in this case, the NA values in b will remain NA after the addition.

If you want different behavior, for example if you want NA + 5 = 5, then you need to convert the NA values to 0 in the parts of the array you care about before doing the addition

To replace all NAs with 0:

b[is.na(b)] <- 0

To only do that in b[,,,2]:

b[,,,2][is.na(b[,,,2])] <- 0
divibisan
  • 11,659
  • 11
  • 40
  • 58
  • That works for when I have numbers for the elements, but how can I make NA + 5 = 5, without adding zeros because those have a different meaning in my dataset? Zeros are non-detections of an individual, whereas NA is no sampling in a given combination of row and column. – Bruna Amaral Mar 03 '23 at 20:55
  • By default NA+5=NA. If that's what you want, just add 5 – divibisan Mar 03 '23 at 20:55
  • I would like NA + 5 = 5 - my bad! – Bruna Amaral Mar 03 '23 at 20:56
  • 1
    Then, that's what the second block does. Convert the desired NA values to 0 before the addition, and they'll behave that way. – divibisan Mar 03 '23 at 20:58
  • Thank you! It makes sense, but this line of code (`is.na(b[,,,2]) <- 0`) is not getting rid of the NAs when I run it – Bruna Amaral Mar 03 '23 at 21:27
  • 1
    This is not correct. `\`is.na<-\`` is not used to remove `NA` but rather to invoke them, ie your code will convert the value at position `0` to `NA` eg `x <- 1:3` `is.na(x) <- 2` means replace `x[2]` with NA – Onyambu Mar 03 '23 at 21:29
  • @onyambu You're right, that was stupid of me. I needed to use it to subset – divibisan Mar 03 '23 at 21:38
  • 1
    @BrunaAmaral onyambu pointed out the problem. It should work now – divibisan Mar 03 '23 at 21:39
  • It is working now with my real dataset - Thank you, I appreciate the help! – Bruna Amaral Mar 03 '23 at 21:43
1

We can do

replace(b, is.na(b), 0) + 5
# , , 1, 1
# 
#      [,1] [,2]
# [1,]    6   10
# [2,]    7   11
# [3,]    8   12
# [4,]    9   13
# 
# , , 2, 1
# 
#      [,1] [,2]
# [1,]   14   18
# [2,]   15   19
# [3,]   16   20
# [4,]   17   21
# 
# , , 3, 1
# 
#      [,1] [,2]
# [1,]   22   26
# [2,]   23   27
# [3,]   24   28
# [4,]   25   29
# 
# , , 1, 2
# 
#      [,1] [,2]
# [1,]   30   34
# [2,]   31   35
# [3,]   32   36
# [4,]   33   37
# 
# , , 2, 2
# 
#      [,1] [,2]
# [1,]   38   42
# [2,]   39   43
# [3,]   40   44
# [4,]   41   45
# 
# , , 3, 2
# 
#      [,1] [,2]
# [1,]   46   50
# [2,]   47   51
# [3,]   48   52
# [4,]   49    5

Disclaimer: This answer refers to "I would like to sum 5 to each element of an array" where NA should be considered a 0.

jay.sf
  • 60,139
  • 8
  • 53
  • 110