Remove '%' from numeric matrix - r

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

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

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

R indexing arrays. How to index 3 dimensional array by using a matrix for the 3rd dimension

I'm having a question about indexing 3 dim arrays.
Say I have a 3 dimensional array
x<- c(1:36)
dim(x) <- c(3,4,3)
Now I want to extract values out of this array according to a matrix holding the 3rd dimension indices for all [i,j] positions.
y <- c(rep(1,4),rep(2,4),rep(3,4))
dim(y) <- c(3,4)
y
[,1] [,2] [,3] [,4]
[1,] 1 1 2 3
[2,] 1 2 2 3
[3,] 1 2 3 3
So the result should be giving this:
[,1] [,2] [,3] [,4]
[1,] 1 4 19 34
[2,] 2 17 20 35
[3,] 3 18 33 36
Is there some elegant way to do this? I know how to use two for loops to go over the array, but this is too slow for my data.
help("[") tells us this:
Matrices and arrays
[...]
A third form of indexing is via a numeric matrix with the one column for each dimension: each row of the
index matrix then selects a single element of the array, and the
result is a vector.
Thus, we transform your y matrix to a shape that conforms with this.
library(reshape2)
z <- x[as.matrix(melt(y))]
dim(z) <- dim(y)
# [,1] [,2] [,3] [,4]
#[1,] 1 4 19 34
#[2,] 2 17 20 35
#[3,] 3 18 33 36
I'm looking at this as an opportunity for some code golf. It's definitely possible to do this as a one-liner:
> `dim<-`(x[cbind(c(row(y)), c(col(y)), c(y))], dim(y))
[,1] [,2] [,3] [,4]
[1,] 1 4 19 34
[2,] 2 17 20 35
[3,] 3 18 33 36
As #Roland's answer shows, matrix/array indexing involves creating an n-column matrix and setting the columns equal to row, column, etc. position of each dimension of an n-dimensional array. We can use the row() and col() functions to extract the row and column positions of each element in y:
> row(y)
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
> col(y)
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 1 2 3 4
[3,] 1 2 3 4
and y itself gives the third-dimension positions. wrapping each of those in c() turns them into a vector, so that they can be cbind-ed together to create an extraction matrix.
Then, there's just some fun use of dim<-() to fit it all on one line.

How to "customize" my elements in a matrix R

I wanna build an nxm matrix, n< m, and i want each element Mij = i^j
Any ideas? I tried multiplying various vectors etc but i never get the correct result.
n <- 3
m <- 4
outer(seq_len(n), seq_len(m), "^")
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 2 4 8 16
#[3,] 3 9 27 81
You can also use sapply:
t(sapply(1:n, `^`, 1:m))
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 2 4 8 16
#[3,] 3 9 27 81
Or even faster:
matrix(1:n, ncol=m, nrow=n)^matrix(1:m, ncol=m, nrow=n, byrow=T)
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 2 4 8 16
#[3,] 3 9 27 81

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