I have two matrices:
x
A B C
2 3 4
3 4 5
and y
D E
1 2
3 2
How can I subtract the combination of elements within columns? Giving me the following result:
AD AE BD BE CD CE
1 0 2 1 3 2
0 1 1 2 2 3
I have tried applying outer, but can't make it work with matrices. Would vectorizing a function be a solution? I have tried the code below, but it doesn't seem to work.
vecfun= Vectorize(fun)
fun=function(a,b)(a-b)
outer(x,y, vecfun)
Thanks in advance for any advice.
This doesn't use outer, but gets your intended result:
> do.call(cbind,lapply(1:ncol(x),function(i) x[,i]-y))
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 2 1 3 2
[2,] 0 1 1 2 2 3
Here's another way without loops/*apply family (assuming your matrices are x and y):
x[ , rep(seq_len(ncol(x)), each=ncol(y))] - y[, rep(seq_len(ncol(y)), ncol(x))]
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 2 1 3 2
[2,] 0 1 1 2 2 3
I'm not sure if it'll be faster, yet. But I thought it is an interesting approach. Also this would take twice the memory of your resulting matrix during computation.
Related
I want to create x randomised matrices where only the columns are permuted but the rows are kept constant. I already took a look at permatful() in the vegan package. Nevertheless, i was not able to generate the desired result even though i am quite sure that this should be possible somehow.
df = matrix(c(2,3,1,4,5,1,3,6,2,4,1,3), ncol=3)
This is (one possible) desired result
[,1] [,2] [,3]
[1,] 2 5 2
[2,] 3 1 4
[3,] 1 3 1
[4,] 4 6 3
v
v permutation
v
[,1] [,2] [,3]
[1,] 5 2 2
[2,] 1 4 3
[3,] 3 1 1
[4,] 6 3 4
I tried something like permatfull(df, times=1, fixedmar = "rows", shuffle = "samp") which results in
[,1] [,2] [,3]
[1,] 5 2 2
[2,] 1 4 3
[3,] 3 1 1
[4,] 3 4 6
Now column 1 (originally column 2) has changed from 5,1,3,6 to 5,1,3,3.
Anyone an idea why I do not get the expected result?
Thanks in Advance,
Christian
I have a matrix of type numeric, with dim 10000 * 50. Now I want to find the index of top 5 elements in every row in the order of their values. e.g. a sample might look like :
set.seed(2)
v1 <- matrix(runif(20 , 0 ,20 ) , 2 ,10)
v1
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,] 3.697645 11.466527 18.87679 2.58318 9.36037 11.053481 15.210266 8.105644 19.527970 8.896185
#[2,] 14.047481 3.361038 18.86950 16.66898 10.99967 4.777895 3.616402 17.070969 4.516509 1.499588
Then I want the output to look like :
#[1,] 9 3 7 2 6
#[2,] 3 8 4 1 5
I could find only this question, which explains how to find top n elements, but not in the order of values.
apply() is perfect for row-wise operations on matrices. You could do
t(apply(v1, 1, function(x) order(-x)[1:5]))
# [,1] [,2] [,3] [,4] [,5]
# [1,] 9 3 7 2 6
# [2,] 3 8 4 1 5
This runs the order() function row-wise down the matrix v1 then takes the first five values for each one, transposing the result since you specify rows not columns.
This can also be done with data.table after melting into 'long' format, grouped by 'Var1', we get the order of 'value'
library(reshape2)
library(data.table)
setDT(melt(v1))[, head(order(-value),5), Var1]
# Var1 V1
#1: 1 9
#2: 1 3
#3: 1 7
#4: 1 2
#5: 1 6
#6: 2 3
#7: 2 8
#8: 2 4
#9: 2 1
#10: 2 5
Or using base R
ave(-v1, row(v1), FUN = order)[,1:5]
# [,1] [,2] [,3] [,4] [,5]
#[1,] 9 3 7 2 6
#[2,] 3 8 4 1 5
I need to write a function in R that creates a matrix of increasing concentric rings of numbers. This function's argument is a number of layers. For example, if x = 3, matrix will look like following:
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
I have no idea how to do it. I would really appreciate any suggestions.
1) Try this:
x <- 3 # input
n <- 2*x-1
m <- diag(n)
x - pmax(abs(row(m) - x), abs(col(m) - x))
giving:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 1 2 2 2 1
[3,] 1 2 3 2 1
[4,] 1 2 2 2 1
[5,] 1 1 1 1 1
2) A second approach is:
x <- 3 # input
n <- 2*x-1
mid <- pmin(1:n, n:1) # middle row/column
outer(mid, mid, pmin)
giving the same result as before.
3) yet another approach having some similarities to the prior two approaches is:
x <- 3 # input
n <- 2*x-1
Dist <- abs(seq_len(n) - x)
x - outer(Dist, Dist, pmax)
Note: The above gives the sample matrix shown in the question but the subject of the question says the rings should be increasing which may mean increasing from the center to the outside so if that is what is wanted then try this where m, mid and Dist are as before:
pmax(abs(row(m) - x), abs(col(m) - x)) + 1
or
x - outer(mid, mid, pmin) + 1
or
outer(Dist, Dist, pmax) + 1
Any of these give:
[,1] [,2] [,3] [,4] [,5]
[1,] 3 3 3 3 3
[2,] 3 2 2 2 3
[3,] 3 2 1 2 3
[4,] 3 2 2 2 3
[5,] 3 3 3 3 3
Try this:
x<-3
res<-matrix(nrow=2*x-1,ncol=2*x-1)
for (i in 1:x) res[i:(2*x-i),i:(2*x-i)]<-i
res
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 1 1 1 1
#[2,] 1 2 2 2 1
#[3,] 1 2 3 2 1
#[4,] 1 2 2 2 1
#[5,] 1 1 1 1 1
A recursive solution for kicks (odd n only)
f <- function(n) if (n == 1) 1 else `[<-`(matrix(1,n,n), 2:(n-1), 2:(n-1), 1+Recall(n-2))
f(5)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 1 1 1 1
# [2,] 1 2 2 2 1
# [3,] 1 2 3 2 1
# [4,] 1 2 2 2 1
# [5,] 1 1 1 1 1
Here's the logic, implement it yourself in R.
Create a matrix with number of rows and columns equal to 2*x-1 and
fill it with zeros and start traversing the array from (0,0) to
(2*x-2,2*x-2).
Now, at each cell, calculate the 'level' of the cell. The level of
the cell is the nearest distance of it from the four borders of
the matrix, i.e. min(i,j,2*x-2-i,2*x-2-j).
This 'level' value is the one to be put in the cell.
This question already has answers here:
interleave rows of matrix stored in a list in R
(2 answers)
Closed 9 years ago.
There is a function in Mathematica called "Riffle" that can be used for inserting columns of a matrix between columns of another matrix.For example, for m1 and m2 matrices like these:
m1= 1 1 1
1 1 1
1 1 1
m2=2 2 2
2 2 2
2 2 2
it creates
1 2 1 2 1 2
1 2 1 2 1 2
1 2 1 2 1 2
is there any equivalent function in R for doing this?
Assuming that you matrices have equal dimensions, you might use this little trick
m <- rbind(m1, m2)
dim(m) <- rev(dim(m))
m
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 1 2 1 2
[2,] 1 2 1 2 1 2
[3,] 1 2 1 2 1 2
Another option would be to use the interleave function from the gdata package. The function interleaves rows not columns, so you need to transpose your matrices back and forth.
m <- t(interleave(t(m1), t(m2)))
m
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 1 2 1 2
[2,] 1 2 1 2 1 2
[3,] 1 2 1 2 1 2
Don't know if it already exists (never seen it), but it is not to difficult to write:
riffle <- function(a,b) {
if (!all(dim(a) == dim(b))) stop("dimensions do not match")
array(rbind(a, b), dim=c(dim(a)[1], dim(a)[1]+dim(b)[1]))
}
I will explain my problem in two different ways, please pick the one you understand better. If something's unclear please, tell me in the comments.
Version 1
For the sake of trying to make it clearer I will explain the same problem frm another point of view:
I have a binary matrix with 5 columns and 3 rows:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 0 0
[2,] 0 0 1 1 0
[3,] 0 0 0 1 1
I am interested in (almost) all the versions of this matrix by permuting only the rows. There is one constraint: I only want the permutations where each column has at least one 1. As said above, I already calculated that there are 370 possibilities of permuting the rows maintaing at leat one 1 in each column. My question here is, is there a possibility obtaining these matrices without having to run through all the 1000 possible permutations?
Version 2
I would like to calculate some probabilities, for wich I have 3 tables of elements which with each 10 columns which need to be combined.
Table 1: combn(5,3) -> 10 combinations
> combn(5,3)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 1 1 1 1 1 2 2 2 3
[2,] 2 2 2 3 3 4 3 3 4 4
[3,] 3 4 5 4 5 5 4 5 5 5
Table 2 & 3: combn(5,2) -> 10 combinations
> combn(5,2)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 1 1 1 2 2 2 3 3 4
[2,] 2 3 4 5 3 4 5 4 5 5
Now I need to have all the combinations of the created groups, but only those who contain all possible elements at least once (1,2,3,4,5). There are 1000 possible combinations of which I am only interested in 370.
The only solution I can think about is to run through all the possible combinations (using expand.grid() and check if all elements are present. I would hope there is an easier solution to this. Meanwhile this example is doesnt pose to much trouble to calculate, as soon as the number grow I could save lots of computation time if I could obtain directly only the combinations I am intersted in.