3D matrix summation? - r

Is there any way to sum 3 dimensional matrix?
For example if you have data
m<-array(c(1:9,18:26,30:38),dim=c(3,3,3))
, , 1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
, , 2
[,1] [,2] [,3]
[1,] 18 21 24
[2,] 19 22 25
[3,] 20 23 26
, , 3
[,1] [,2] [,3]
[1,] 30 33 36
[2,] 31 34 37
[3,] 32 35 38
And your answer will be: 549.
Also, if there six 3by3 matrices, how can be every two matrices summed and printed? With for loop?

Call sum() for each of your dimensions, here three:
R> m<-array(c(1:9,18:26,30:38),dim=c(3,3,3))
R> sum(sum(sum(m)))
[1] 549
R>
Or drop dimensions and call sum() on what is now a single vector:
R> sum(c(m))
[1] 549
R>
Edit I overcomplicated things. A 3-array is still just a vector, so all it takes is
R> sum(m)
[1] 549
R>
Thanks to #thelatemail for the cluebat.

Related

How to multiply a matrix by a known vector to return an array

Good afternoon!
Assume we have a vector and a matrix :
v = c(2,3,4)
[1] 2 3 4
m=matrix(1:9,ncol=3)
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
I'm searching an efficient way ( or built-in function ) to get three matrices m1 , m2 , m3 such that :
m1=v[1]*m
m2=v[2]*m
m3=v[3]*m
We could obtain this using a 3d-array :
my_fct<-function(m,v){
f=array(data=rep(NA,nrow(m)*ncol(m)*length(v)),dim = c(nrow(m),ncol(m),length(v)))
for (j in c(1:length(v))){
f[,,j]=v[j]*m
}
return(f)
}
my_fct(m,v)
, , 1
[,1] [,2] [,3]
[1,] 2 8 14
[2,] 4 10 16
[3,] 6 12 18
, , 2
[,1] [,2] [,3]
[1,] 3 12 21
[2,] 6 15 24
[3,] 9 18 27
, , 3
[,1] [,2] [,3]
[1,] 4 16 28
[2,] 8 20 32
[3,] 12 24 36
I hope my request is clear!
Thank you a lot for help !
As 'v' is a vector and we want each element to be multiplied by the same matrix 'm', an option is to loop over the element of 'v' and do the multiplication
lapply(v, `*`, m)
-output
[[1]]
[,1] [,2] [,3]
[1,] 2 8 14
[2,] 4 10 16
[3,] 6 12 18
[[2]]
[,1] [,2] [,3]
[1,] 3 12 21
[2,] 6 15 24
[3,] 9 18 27
[[3]]
[,1] [,2] [,3]
[1,] 4 16 28
[2,] 8 20 32
[3,] 12 24 36
Another base R option
> Map(`*`, list(m), v)
[[1]]
[,1] [,2] [,3]
[1,] 2 8 14
[2,] 4 10 16
[3,] 6 12 18
[[2]]
[,1] [,2] [,3]
[1,] 3 12 21
[2,] 6 15 24
[3,] 9 18 27
[[3]]
[,1] [,2] [,3]
[1,] 4 16 28
[2,] 8 20 32
[3,] 12 24 36

Remove '%' from numeric matrix

Quick question, how can I remove unwanted characters from a matrix that should be numeric?
I always get confused with apply functions, and I don't seem to be able to get this right...
Check this MWE, I have some unwanted "%" after some of the numbers, and they need to be removed. I know how to do it on a variable (column) basis, but how to apply it to the whole matrix properly?
> a=matrix(c('7%','11%',22,'65%',7,8,'1%','77%','34%'), ncol=3)
> a
[,1] [,2] [,3]
[1,] "7%" "65%" "1%"
[2,] "11%" "7" "77%"
[3,] "22" "8" "34%"
> as.numeric(sub("%$","",a[,1]))
[1] 7 11 22
Expected output:
> a
[,1] [,2] [,3]
[1,] 7 65 1
[2,] 11 7 77
[3,] 22 8 34
On matrix you can apply the transformation directly :
b <- a
b <- as.numeric(sub('%$','', b))
dim(b) <- dim(a)
b
# [,1] [,2] [,3]
#[1,] 7 65 1
#[2,] 11 7 77
#[3,] 22 8 34
We could do this in a single step
matrix(readr::parse_number(a), dim(b))
# [,1] [,2] [,3]
#[1,] 7 65 1
#[2,] 11 7 77
#[3,] 22 8 34

Apply function in R behaving differently

I was studying apply functions in R. Here is what i tried out:
> x <- array(1:9,c(3,3))
> x
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> apply(x,1,function(x) x * 10)
[,1] [,2] [,3]
[1,] 10 20 30
[2,] 40 50 60
[3,] 70 80 90
My question is why is it like this? I was thinking, apply will apply the user defined function to each element in the row so that it will look as below. Why does it differ? Is there anything wrong in my understanding.
[,1] [,2] [,3]
[1,] 10 40 70
[2,] 20 50 80
[3,] 30 60 90

From dataframe to array, by row

I have a dataframe "df", and I would like to transform it into an array BY ROW, for example:
> df
x y
1 1 21
2 2 22
3 3 23
4 4 24
5 5 25
6 6 26
7 7 27
8 8 28
#Into this array:
> array.df
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 21 2 22
[2,] 3 23 4 24
, , 2
[,1] [,2] [,3] [,4]
[1,] 5 25 6 26
[2,] 7 27 8 28
Can anyone help me with the code? Thanks.
Quite an ugly solution, but it gets the job done. Maybe someone else has a better way of doing this. In the meantime, it should do.
install.packages("reshape2")
library("reshape2")
df
x y
1 1 21
2 2 22
3 3 23
4 4 24
5 5 25
6 6 26
7 7 27
8 8 28
myarray <- array(cbind(matrix(melt(t(df))[1:8,3],byrow = T, ncol = 4),matrix(melt(t(df))[9:16,3],byrow = T, ncol = 4)), c(2,4,2))
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 21 2 22
[2,] 3 23 4 24
, , 2
[,1] [,2] [,3] [,4]
[1,] 5 25 6 26
[2,] 7 27 8 28
I will try and explain:
The idea is to transpose the data frame with t() and then melt it using the melt() function from the reshape2 package. Upon reshaping the data, you want to grab the 3rd column and then create two matrices from it by row. Then, you will need to cbind those matrices into one matrix. And finally, use that matrix to get the array you want with dimension c(2,4,2).
I hope this makes sense.
Here is another not so elegant solution:
df <- data.frame(x=1:8, y=21:28)
vec <- as.vector(t(df)) # transpose df and then turn into a single vector
arr <- array(vec, dim=c(4,2,2)) # create array with first 2 dimensions transposed
lis <- lapply(1:2, function(x) { t(arr[,,x]) }) # transpose the first 2 dimensions
array(do.call(cbind, lis), c(2,4,2)) # convert back to array format
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 21 2 22
[2,] 3 23 4 24
, , 2
[,1] [,2] [,3] [,4]
[1,] 5 25 6 26
[2,] 7 27 8 28
Using only the base package:
df <- data.frame(x = 1:8, y = 21:28)
array.df <- array(
data = as.vector(t(df)),
dim = c(4,2,2))
array.df <- aperm(a = array.df, perm = c(2,1,3))
print(array.df)
Just thought of a simpler base R answer for this using some array manipulation:
apply(array(t(df), dim=c(4,2,2)), c(1,3), t)
#, , 1
#
# [,1] [,2] [,3] [,4]
#[1,] 1 21 2 22
#[2,] 3 23 4 24
#
#, , 2
#
# [,1] [,2] [,3] [,4]
#[1,] 5 25 6 26
#[2,] 7 27 8 28
Use some matrix trickery to fill by row and then reshape again. sapply's simplify="array" ensures the array output:
sapply(
split(df, rep(1:2,each=nrow(df)/2)),
function(x) matrix(c(matrix(unlist(x),byrow=TRUE,ncol=2)),nrow=2),
simplify="array"
)
#, , 1
#
# [,1] [,2] [,3] [,4]
#[1,] 1 21 2 22
#[2,] 3 23 4 24
#
#, , 2
#
# [,1] [,2] [,3] [,4]
#[1,] 5 25 6 26
#[2,] 7 27 8 28

Delete row based on the value of the rows above

I have a the following data set:
data <- cbind(c(1,2,3,4,5,6,7,8,9,10,11),c(1,11,21,60,30,2,61,12,3,35,63))
I would like to select the rows for which the number in the second column is greater than the highest number reached up to that point. The result should look like this.
[,1] [,2]
[1,] 1 1
[2,] 2 11
[3,] 3 21
[4,] 4 60
[5,] 7 61
[6,] 11 63
You want to try cummax:
> d[ d[,2] == cummax(d[,2]) ,]
[,1] [,2]
[1,] 1 1
[2,] 2 11
[3,] 3 21
[4,] 4 60
[5,] 7 61
[6,] 11 63
PS. data is an internal R function, so, since R variables and functions share the namespace (R design was influenced by Scheme, which is a "Lisp-1"), your variable shadows the system function.
The cummax function should work well
data[ data[,2]==cummax(data[,2]),]
returns
[,1] [,2]
[1,] 1 1
[2,] 2 11
[3,] 3 21
[4,] 4 60
[5,] 7 61
[6,] 11 63
as desired.

Resources