Apply family of functions in R - r

I have a double loop in this form:
for (j in 1:col(mat))
{
for (i in 1:nrow(mat))
{
decision[i][j] = ifelse(mat[i][j] > 3, 1, 0)
}
}
Is there any way this functionality can be achieved through one of the apply functions with significantly improved speed?

You don't need any loops. If you create a matrix that looks like this
mat<-matrix(sample(1:10, 5*7, replace=T), ncol=7)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#[1,] 9 6 10 7 6 10 6
#[2,] 7 6 3 3 6 8 3
#[3,] 7 9 7 5 6 7 6
#[4,] 2 3 8 6 10 1 5
#[5,] 4 1 5 6 1 10 6
then you can just do
decision <- (mat>3)+0
decision;
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#[1,] 1 1 1 1 1 1 1
#[2,] 1 1 0 0 1 1 0
#[3,] 1 1 1 1 1 1 1
#[4,] 0 0 1 1 1 0 1
#[5,] 1 0 1 1 0 1 1

R is a vectorized language, so for this kind of simple manipulation of a matrix apply type functions are not needed, just do:
decision <- ifelse(mat > 3, 1, 0)
(I'm assuming you want to iterate through the elements of the matrix, which means you would say ncol(mat) in your loop; col gives something rather different).

Related

Find minimum value of two dice roll in R

Instead of using a loop to find a minimum of two dice roll in R such as:
Min <- matrix(0, nrow=6, ncol=6)
d1 <- 1:6
d2 <- 1:6
for(k in 1:6){
for(j in 1:6){
Min[k,j] <- min( c(d1[k], d2[j]) )
}
}
Is there a simpler way or shorter code to get the following result?
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 1 1 1
[2,] 1 2 2 2 2 2
[3,] 1 2 3 3 3 3
[4,] 1 2 3 4 4 4
[5,] 1 2 3 4 5 5
[6,] 1 2 3 4 5 6
outer(d1,d2,pmin)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 1 1 1
[2,] 1 2 2 2 2 2
[3,] 1 2 3 3 3 3
[4,] 1 2 3 4 4 4
[5,] 1 2 3 4 5 5
[6,] 1 2 3 4 5 6
*apply loops are loops just like for loops but they make nice one-liners.
sapply(1:6, function(y) sapply(1:6, function(x) min(x, y)))
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 1 1 1 1 1 1
#[2,] 1 2 2 2 2 2
#[3,] 1 2 3 3 3 3
#[4,] 1 2 3 4 4 4
#[5,] 1 2 3 4 5 5
#[6,] 1 2 3 4 5 6
#user2974951's answer is way better, but here's my solution anyways:
a <- matrix(0, nrow = 6, ncol = 6)
for (i in 6:1){
a[,i] <- i
a[i,] <- i
}
a
#> [,1] [,2] [,3] [,4] [,5] [,6]
#>[1,] 1 1 1 1 1 1
#>[2,] 1 2 2 2 2 2
#>[3,] 1 2 3 3 3 3
#>[4,] 1 2 3 4 4 4
#>[5,] 1 2 3 4 5 5
#>[6,] 1 2 3 4 5 6

How to select unique columns in an R matrix

I want to select the unique columns in the matrix six on a simulation as follows:
> set.seed(3)
> sam = replicate(100, sample(1:3, 4, rep = T))
> (six = sam[,colSums(sam)==6])
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 2 1 1 1 1 1 1 1 2 1
[2,] 2 2 3 1 1 2 2 1 2 2
[3,] 1 1 1 1 2 1 1 3 1 1
[4,] 1 2 1 3 2 2 2 1 1 2
I would like to end up with a matrix as:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 2 1 1 1 1 1
[2,] 2 2 3 1 1 1
[3,] 1 1 1 1 2 3
[4,] 1 2 1 3 2 1
Use unique function with MARGIN=2 and it will return a matrix with duplicated columns removed, by default, unique removes duplicated rows:
unique(six, MARGIN = 2)
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 2 1 1 1 1 1
#[2,] 2 2 3 1 1 1
#[3,] 1 1 1 1 2 3
#[4,] 1 2 1 3 2 1
We can use duplicated
six[,!duplicated(t(six))]
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 2 1 1 1 1 1
#[2,] 2 2 3 1 1 1
#[3,] 1 1 1 1 2 3
#[4,] 1 2 1 3 2 1

R: Matrix sorting by only part of a column

I have a matrix, say:
c <- c(1,2,3,4,5,0,1,-5,3,1,-3,2,-2,1,2,0,1,0,3,3,5,-5,3,-1,0)
M <- matrix(c, byrow=T, nrow=5)
M
So:
M
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 0 1 -5 3 1
[3,] -3 2 -2 1 2
[4,] 0 1 0 3 3
[5,] 5 -5 3 -1 0
I know how to sort M by absolute values of column [,3] (for example):
Ma <- abs(M)
Ms <- M[order(Ma[,3], decreasing = T),]
Ms
So:
Ms
[,1] [,2] [,3] [,4] [,5]
[1,] 0 1 -5 3 1
[2,] 1 2 3 4 5
[3,] 5 -5 3 -1 0
[4,] -3 2 -2 1 2
[5,] 0 1 0 3 3
But what I would like to have is M sorted not by the entire column [,3], but only by the last 3 absolute values, so that the first two lines of M are not changed:
Ms
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 0 1 -5 3 1
[3,] 5 -5 3 -1 0
[4,] -3 2 -2 1 2
[5,] 0 1 0 3 3
I couldn't find how to do this in a simple way. Any idea ?
Thanks.
We can try
M[(nrow(M)-2):nrow(M),] <- tail(M,3)[order(tail(Ma[,3],3), decreasing=TRUE),]
M
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 2 3 4 5
#[2,] 0 1 -5 3 1
#[3,] 5 -5 3 -1 0
#[4,] -3 2 -2 1 2
#[5,] 0 1 0 3 3
M[c(1:2,2L+order(abs(M[-1:-2,3L]),decreasing=T)),];
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 0 1 -5 3 1
## [3,] 5 -5 3 -1 0
## [4,] -3 2 -2 1 2
## [5,] 0 1 0 3 3

Summing rows of rolling columns

I need to apply a rolling function that sums the rows of every two columns, so the rows of columns 1&2 will be summed, 3&4, etc.
m<-matrix(c(1,2,3,4,5,3,4,5,6,2,4,6,6,7,3,2,4,4,5,7),nrow=2,byrow=T)
I have looked at many functions including apply, rollapply, aggregate, etc. but cant seem to find one that roll sums the rows of specified columns.
I am more than capable of writing the code out the long way however am looking for an efficient solution which most likely involves a function.
sum1<-(m[,1]+m[,2])
sum2<-(m[,3]+m[,4])
sum3<-(m[,5]+m[,6])
sum4<-(m[,7]+m[,8])
sum5<-(m[,9]+m[,10])
cbind(sum1,sum2,sum3,sum4,sum5)
Thanks!
You can use this approach:
m[,seq(1, ncol(m),2)] + m[,seq(2, ncol(m), 2)]
# [,1] [,2] [,3] [,4] [,5]
#[1,] 3 7 8 9 8
#[2,] 10 13 5 8 12
You can use a matrix multiply:
> n <- ncol(m)/2
> S <- diag(n)[rep(1:n, each=2),]
> S
[,1] [,2] [,3] [,4] [,5]
[1,] 1 0 0 0 0
[2,] 1 0 0 0 0
[3,] 0 1 0 0 0
[4,] 0 1 0 0 0
[5,] 0 0 1 0 0
[6,] 0 0 1 0 0
[7,] 0 0 0 1 0
[8,] 0 0 0 1 0
[9,] 0 0 0 0 1
[10,] 0 0 0 0 1
> m %*% S
[,1] [,2] [,3] [,4] [,5]
[1,] 3 7 8 9 8
[2,] 10 13 5 8 12
Another approach would be to convert m to a 3 dimensional array, then sum over the columns:
> X <- m
> dim(X) <- c(2,2,5)
> colSums(aperm(X, c(2,1,3)))
[,1] [,2] [,3] [,4] [,5]
[1,] 3 7 8 9 8
[2,] 10 13 5 8 12

how to bind the same vector multiple times?

How can I bind the same vector o = c(1,2,3,4) multiple times to get a matrix like:
o = array(c(1,2,3,4,1,2,3,4,1,2,3,4), dim(c(4,3))
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 2 2 2
[3,] 3 3 3
[4,] 4 4 4
In a nicer way than: o = cbind(o,o,o) and maybe more generalized (duplicate)? I need this to specify colors for elements in textplot.
R recycles. It's very eco-friendly:
o=c(1,2,3,4)
> matrix(o,nrow = 4,ncol = 4)
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
[4,] 4 4 4 4
You can use replicate
> o = c(1,2,3,4)
> replicate(4, o)
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
[4,] 4 4 4 4
You can use outer
outer(1:4,1:4,function(x,y)x)
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 2 2 2 2
[3,] 3 3 3 3
[4,] 4 4 4 4

Resources