Octave map over matrix with row and column indexes - functional-programming

So basically I'm looking for something like arrayfun(#(value, rowIdx, colIdx), matrix).
I need to create one matrix from another based on it's values and their indexes, is there a way to avoid for-loops?

You can create matrices for the row and column indices using meshgrid and the size of your matrix. You can then use all three of these matrices to calculate the result.
[col_index, row_index] = meshgrid(1:size(matrix, 1), 1:size(matrix, 2));
% Now do some calculations using that
new_matrix = matrix + row_index * col_index;

Related

Looking for a function in R to sum rows and cols for matrix reduction

Looking for a R function to sum rows and columns.
I have a matrix (6x6). I want to sum [1,1]+[1,2]+[2,1]+[2,2], and then the same for the rest of the matrix, finally I want to get a 3x3 matrix, in which each [i,j] as the respective sum.
You can try something like this:
#define matrix with no. of columns and rows
m<-matrix(1:6,nrow = 6,ncol = 6)
m_req<-m
for(i in 1:nrow(m_req)){
if(i!=nrow(m_req)){
m_req[i,]<-m_req[i,]+m_req[i+1,]
m_req[,i]<-m_req[,i]+m_req[,i+1]
}
}
req_columns<-seq(1,ncol(m_req),by=2)
m_req<-m_req[req_columns,req_columns]

How to sum a matrix cell value into another by row/column names?

Imagine I have an overall list of authors
Authors <- c("Abel","Babel","Cain","Devil","Esau")
with it I build an overall adjacency matrix, initialized with zeroes
allAuthors <- matrix(0L,nrow=length(Authors),ncol=length(Authors),dimnames=list(Authors,Authors))
now I am stumbling on a paper coAuthored by these three guys
paperAuthors <- c("Babel","Cain","Devil")
and build another adjacency matrix of their collaboration, initialized with all 1s
coAuth <- matrix(1L,nrow=length(paperAuthors),ncol=length(paperAuthors),dimnames=list(paperAuthors,paperAuthors))
Question :
How do I sum the coAuth matrix cell values into the corresponding allAuthors
matrix cells using the row and colum names as indices ?
In other words I'd like to obtain the cells of the allAuthors matrix having 1s at the intersection of the paperAuthors authors while all other remain 0s.
Thank you very much
First we get the indexes in the coAuth matrix.
ind <- which(coAuth == 1, arr.ind = TRUE)
Now we have to find the corresponding indexes in the allAuthors matrix.
ind.allAuthors <- cbind(
match(rownames(coAuth), rownames(allAuthors))[ind[, 'row']],
match(colnames(coAuth), colnames(allAuthors))[ind[, 'col']])
And now we can sum the elements from both matrices:
allAuthors[ind.allAuthors] <- allAuthors[ind.allAuthors] + 1
Would subsetting work for your needs or do you need to define new matrix summation operation?
allAuthors[paperAuthors, paperAuthors] <-
allAuthors[paperAuthors, paperAuthors] + 1
allAuthors

Assignment of value in R

How can I improve the speed of following codes?
for (i in 1:nrow(training)){
score[training[i,1],training[i,2],training[i,4]] = training[i,3]
}
Training is a matrix with four columns. I just want to build an array which the value is training[i,3] according the formula above.
Thanks!
You can index using a matrix. Here is the relevant part of ['s documentation:
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.
So in your case, the for loop can be replaced with:
score[training[, c(1, 2, 4)]] <- training[, 3]

generate all possible column combinations and create one matrix for each of them in R

I have a matrix like this one:
myarray=cov(matrix(rexp(200),50,10))
I would like to generate all possible combinations of columns and compute the correlation matrix for each combination, if possible, using column numbers instead of names. In a second step I would like to compute the determinant of each matrix so maybe there is an efficient way to do it.
Here is one way:
list.of.matrices <- apply(expand.grid(rep(list(c(FALSE, TRUE)), ncol(myarray))),
1, function(j)myarray[, j, drop = FALSE])
length(list.of.matrices)
# [1] 1024
Then do something like:
result <- sapply(list.of.matrices, function_of_your_choice)
but note that det can only be applied to square matrices... Please clarify.

selecting columns specified by a random vector in R

I have a large matrix from which I would like to randomly extract a smaller matrix. (I want to do this 1000 times, so ultimately it will be in a for loop.) Say for example that I have this 9x9 matrix:
mat=matrix(c(0,0,1,0,1,0,0,0,1,0,0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,
0,0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,1,1,1,0,0,
1,0,1,0,0,0,0,0,1,0,1,0,0,0,1), nrow=9)
From this matrix, I would like a random 3x3 subset. The trick is that I do not want any of the row or column sums in the final matrix to be 0. Another important thing is that I need to know the original number of the rows and columns in the final matrix. So, if I end up randomly selecting rows 4, 5, and 7 and columns 1, 3, and 8, I want to have those identifiers easily accessible in the final matrix.
Here is what I've done so far.
First, I create a vector of row numbers and column numbers. I am trying to keep these attached to the matrix throughout.
r.num<-seq(from=1,to=nrow(mat),by=1) #vector of row numbers
c.num<-seq(from=0, to=(ncol(mat)+1),by=1) #vector of col numbers (adj for r.num)
mat.1<-cbind(r.num,mat)
mat.2<-rbind(c.num,mat.1)
Now I have a 10x10 matrix with identifiers. I can select my rows by creating a random vector and subsetting the matrix.
rand <- sample(r.num,3)
temp1 <- rbind(mat.2[1,],mat.2[rand,]) #keep the identifier row
This works well! Now I want to randomly select 3 columns. This is where I am running into trouble. I tried doing it the same way.
rand2 <- sample(c.num,3)
temp2 <- cbind(temp1[,1],temp1[,rand2])
The problem is that I end up with some row and column sums that are 0. I can eliminate columns that sum to 0 first.
temp3 <- temp1[,which(colSums(temp1[2:nrow(temp1),])>0)]
cols <- which(colSums(temp1[2:nrow(temp1),2:ncol(temp1)])>0)
rand3 <- sample(cols,3)
temp4 <- cbind(temp3[,1],temp3[,rand3])
But I end up with an error message. For some reason, R does not like to subset the matrix this way.
So my question is, is there a better way to subset the matrix by the random vector "rand3" after the zero columns have been removed OR is there a better way to randomly select three complementary rows and columns such that there are none that sum to 0?
Thank you so much for your help!
If I understood your problem, I think this would work:
mat=matrix(c(0,0,1,0,1,0,0,0,1,0,0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,
0,0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,1,1,1,0,0,
1,0,1,0,0,0,0,0,1,0,1,0,0,0,1), nrow=9)
smallmatrix = matrix(0,,nrow=3,ncol=3)
while(any(apply(smallmatrix,2,sum) ==0) | any(apply(smallmatrix,1,sum) ==0)){
cols = sample(ncol(mat),3)
rows= sample(nrow(mat),3)
smallmatrix = mat[rows,cols]
}
colnames(smallmatrix) = cols
rownames(smallmatrix) = rows

Resources