Apply function in R behaving differently - r

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

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

create a Vandermonde matrix in R

I am new to R and still learning it. I want to m-by-n Vandermonde matrix
I know it can be done via for loops to assign values to corresponding indices within the matrix, but it seems inefficient when m or n is large. I need some advices to have a simpler and efficient way to generate the Vandermonde matrix? Thanks for help in advance!
Use outer like this:
n <- 6; alpha <- 1:5 # test data
outer(alpha, seq(0, n-1), `^`)
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 1 1 1 1 1
## [2,] 1 2 4 8 16 32
## [3,] 1 3 9 27 81 243
## [4,] 1 4 16 64 256 1024
## [5,] 1 5 25 125 625 3125
A base R solution is to define your custom function vander, where sapply + cumprod are used
vander <- function(alpha,n) t(sapply(alpha, function(k) c(1,cumprod(rep(k,n-1)))))
vm1 <- vander(alpha,n)
Another option is from package matrixcalc, in which vandermonde.matrix can make it
vm2 <- matrixcalc::vandermonde.matrix(alpha,n)
Example
Given alpha and n like below
alpha <- 1:4
n <- 5
then you will get
> vm1
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 1 2 4 8 16
[3,] 1 3 9 27 81
[4,] 1 4 16 64 256
> vm2
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 1 2 4 8 16
[3,] 1 3 9 27 81
[4,] 1 4 16 64 256

Flip the matrix

Hi everyone who loves while hates R:
Let's say you want to turn matrix M
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
to N
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 6 5 4
[3,] 9 8 7
All you need to do is
N<-M[,c(3:1)]
And N's structure is still a matrix
However, when you want to turn matrix M
[,1] [,2] [,3]
[1,] 1 2 3
to N
[,1] [,2] [,3]
[1,] 3 2 1
if you do
N<-M[,c(3:1)]
R will give you
N
[1] 3 2 1
N now is a vector! Not a matrix!
My solution is
N<-M%*%diag(3)[,c(3:1)]
which needs big space to store the identity matrix however.
Any better idea?
You're looking for this:
N<-M[,c(3:1),drop = FALSE]
Read ?Extract for more information. This is also a FAQ. This behavior is one of the most common debates folks have about the way things "should" be in R. My general impression is that many people agree that drop = FALSE might be a more sensible default, but that behavior is so old that changing it would be enormously disruptive to vast swaths of existing code.
A=t(matrix(1:25,5,5))
B=matrix(0,5,5)
for(i in 1:5){
B[i,(nrow(A)+1-i)]=1
}
A
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 2 3 4 5
# [2,] 6 7 8 9 10
# [3,] 11 12 13 14 15
# [4,] 16 17 18 19 20
# [5,] 21 22 23 24 25
A%*%B
# [,1] [,2] [,3] [,4] [,5]
# [1,] 5 4 3 2 1
# [2,] 10 9 8 7 6
# [3,] 15 14 13 12 11
# [4,] 20 19 18 17 16
# [5,] 25 24 23 22 21

3D matrix summation?

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.

Resources