Simple way to assign the matrix - r

Is there another way to assign the matrix?
> x<-matrix(NA,nrow=3,ncol=4)
> x
[,1] [,2] [,3] [,4]
[1,] NA NA NA NA
[2,] NA NA NA NA
[3,] NA NA NA NA
One way is x[2:10]<-2:10 t(x) .
[,1] [,2] [,3]
[1,] NA 2 3
[2,] 4 5 6
[3,] 7 8 9
[4,] 10 NA NA
i am asking in general how to assign values to part of matrices (the part of matrices are not matrices,it is only part of it).

In the general case, where the matrix elements you wish to assign may not even be neighbors, you should use both indices with the [<- tools. E.g. (for a larger matrix than your example)
x[1:3,4]<-8:10
or
x[5,c(3,7,11)]<- c(5,3,1)
and so on. If there's a pattern to the replacement locations, you can write loops over the indices of interest.

Related

Transforming NA to specific arrays of a matrix in R

I have a matrix of the form,
mat <- matrix(1:25, 5,5)
that looks like the following:
Now, I need to transform this matrix in the form as shown below:
That is, I want to keep all elements of row 2 and 4 as well as column 2 and 4 and replace all other values with NA. This a just a simple example to explain the problem. My actual matrix size is about 2000 X 2000. Any help would be much appreciated.
Your first and second matrices are a different in that the first one is filled as R would fill a matrix (i.e. column-major order) and the second is row-major.
Assuming that you meant to have identical matrices, your task can be addressed with simple matrix operations:
mat <- matrix(1:25, 5,5)
mat2 <- matrix(NA, 5,5)
mat2[c(2,4),] <- 1
mat2[,c(2,4)] <- 1
mat * mat2
[,1] [,2] [,3] [,4] [,5]
[1,] NA 6 NA 16 NA
[2,] 2 7 12 17 22
[3,] NA 8 NA 18 NA
[4,] 4 9 14 19 24
[5,] NA 10 NA 20 NA
If not, just transpose your initial matrix with t(mat) and follow the same approach as above.
mat = t(mat)
replace(x = mat, which((matrix(row(mat) %in% c(2, 4), NROW(mat), NCOL(mat)) |
matrix(col(mat) %in% c(2, 4), NROW(mat), NCOL(mat))) == FALSE,
arr.ind = TRUE), NA)
# [,1] [,2] [,3] [,4] [,5]
#[1,] NA 2 NA 4 NA
#[2,] 6 7 8 9 10
#[3,] NA 12 NA 14 NA
#[4,] 16 17 18 19 20
#[5,] NA 22 NA 24 NA

How to reconstruct diff data with leading NAs using diffinv in R?

I have a large data matrix (“trial.matrix”) similar to the one below.
[,1] [,2]
[1,] 3 NA
[2,] 5 NA
[3,] 7 NA
[4,] 9 10
[5,] 11 12
[6,] 13 14
My problem requires that I shuffle some rows of the difference version of this matrix and then reconstruct a matrix from the shuffled difference matrix. When I apply diff(trial.matrix) I get:
[,1] [,2]
[1,] 2 NA
[2,] 2 NA
[3,] 2 NA
[4,] 2 2
[5,] 2 2
To reconstruct the original data frame, I need to use cumsum() or diffinv(), e.g.:
new.df <- diffinv(diff(trial.matrix), xi = t(c(3, 10)))
but this gives:
[,1] [,2]
[1,] 3 10
[2,] 5 NA
[3,] 7 NA
[4,] 9 NA
[5,] 11 NA
[6,] 13 NA
Obviously, the beginning value (“xi”) for column 2 has to be applied starting in row 3 (or 4?). I have a number of columns in the real matrix, some with leading NAs and some without. I need to preserve the leading NAs in the reconstruction. I cannot figure out an easy way to reconstruct the columns with NAs in the difference matrix in a straightforward way.
(For each column I am able to construct two vectors, one containing the first non-NA row, and the other containing the first NA value, but cannot figure out a straightforward way to use these.)
Suggestions appreciated.
You can temporarily replace NAs by zeroes:
trial.matrix <- matrix(c(seq(3,13,by=2),rep(NA,3),10,12,14),ncol=2)
xi <- apply(trial.matrix,2,function(cl) cl[which(!is.na(cl))[1]])
z2 <- diff(trial.matrix)
# temporarily replace NAs in the second column by zeroes:
nas <- which(is.na(z2[,2]))
z2[nas,2] <- 0
new.df <- diffinv(z2,xi = t(xi))
# return NAs
new.df[nas,2] <- NA
# [,1] [,2]
# [1,] 3 NA
# [2,] 5 NA
# [3,] 7 NA
# [4,] 9 10
# [5,] 11 12
# [6,] 13 14

subset a matrix, and get NA if index is not valid

I am trying to subset a matrix to always get a 3*3 matrix.
For example, the matrix being subset is a<-matrix(1:15,3,5), usually when I subset it using a[0:2,0:2], I get:
[,1] [,2]
[1,] 1 4
[2,] 2 5
But I want to get something like:
[,1] [,2] [,3]
[1,] NA NA NA
[2,] NA 1 4
[3,] NA 2 5
Force all your 0's to NAs when you select, as well as any 'out-of-bounds' values:
ro <- 0:2
co <- 0:2
a[replace(ro,ro == 0 | ro > nrow(a),NA),
replace(co,co == 0 | co > ncol(a),NA)]
# [,1] [,2] [,3]
#[1,] NA NA NA
#[2,] NA 1 4
#[3,] NA 2 5
This will even work with combinations of the parts you want missing:
ro <- c(1,0,2)
co <- 0:2
a[replace(ro,ro == 0 | ro > nrow(a),NA),
replace(co,co == 0 | co > ncol(a),NA)]
# [,1] [,2] [,3]
#[1,] NA 1 4
#[2,] NA NA NA
#[3,] NA 2 5
You could create your own padding function to fill in space less than 3x3 by NA values
padmatrix <- function(a, dim=c(3,3)) {
stopifnot(all(dim(a)<=dim))
cbind(rep(NA,dim[2]-ncol(a)), rbind(rep(NA,dim[1]-nrow(a)), a))
}
padmatrix(a[1:2, 1:2])
# [,1] [,2] [,3]
# [1,] NA NA NA
# [2,] NA 1 4
# [3,] NA 2 5

Is there a way to reorder the rows and columns of matrix to create a dense corner, in R?

I have a large matrix which comprises 1,2 and missing (coded as NA) values. The matrix has 500000 rows by 10000 columns. There are approximately 0.05% 1- or 2-values, and the remaining values are NA.
I would like to reorder the rows and columns of the matrix so that the top left corner of the matrix comprises a relatively high number of 1s and 2s compared to the rest of the matrix. In other words, I would like to create a relatively datarich subset of the matrix, by reordering the matrix rows and columns.
Is there an efficient method of achieving this in R, perhaps using a library? I would also be interested in solutions in Python or Java, but I would prefer to perform this in R as it is the language that's most familiar to me.
I thought that there maybe a set of optimisation procedures that I could use as my working matrix is too large to do the reorganisation by eye.
I have reverted a set of edits so that the question remains consistent with the current answers.
Like this?
#some sparse data
set.seed(42)
p <- 0.0005
mat <- matrix(sample(c(1, 2, NA), 1e4, TRUE, c(p/2, p/2, 1-p)), ncol=50)
#order columns and rows by the number of NA values in them
mat <- mat[order(rowSums(is.na(mat))), order(colSums(is.na(mat)))]
#only show columns and rows containing non-NA values
mat[rowSums(!is.na(mat)) > 0, colSums(!is.na(mat)) > 0]
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] NA NA NA NA 2 NA
# [2,] NA NA NA NA NA 2
# [3,] NA NA 2 NA NA NA
# [4,] NA 1 NA NA NA NA
# [5,] 1 NA NA NA NA NA
# [6,] NA NA NA 2 NA NA
Something like this?
Rgames> bar
[,1] [,2] [,3] [,4] [,5]
[1,] NA NA NA NA NA
[2,] 1 NA NA NA 3
[3,] NA NA NA NA NA
[4,] 2 NA NA NA 4
[5,] NA NA NA NA NA
Rgames> rab<-bar[order(bar[,1]),]
Rgames> rab
[,1] [,2] [,3] [,4] [,5]
[1,] 1 NA NA NA 3
[2,] 2 NA NA NA 4
[3,] NA NA NA NA NA
[4,] NA NA NA NA NA
[5,] NA NA NA NA NA
Rgames> rab[,order(rab[1,])]
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 NA NA NA
[2,] 2 4 NA NA NA
[3,] NA NA NA NA NA
[4,] NA NA NA NA NA
[5,] NA NA NA NA NA
EDIT, as Roland pointed out, in a more general situation that won't come close. Now, if one is allowed to 'jumble' the rows and columns, this would do it:
for(j in 1:nrow(mfoo)) mat[j,]<-mat[j,order(mat[j,])]
for(j in 1:ncol(mat)) mat[,j]<-mat[order(mat[,j]),j]
I suspect that's not what is desired, so I'll go off and think some more about ordering "criteria"

In R how to control the cycling direction of values when copying in an array?

I would like to copy some values across rows but the default seems to be cycling over columns, is there an elegant way to achieve what I want ?
The following code I have is:
> w = array(NA,dim=c(4,2))
> w
[,1] [,2]
[1,] NA NA
[2,] NA NA
[3,] NA NA
[4,] NA NA
> w[2:4,] = c(2,3)
> w
[,1] [,2]
[1,] NA NA
[2,] 2 3
[3,] 3 2
[4,] 2 3
But I would like the values to be cycled over rows to obtain:
[,1] [,2]
[1,] NA NA
[2,] 2 3
[3,] 2 3
[4,] 2 3
You can write a new transposed assignment function:
`t<-` <- function(x, value)
{
t(matrix(value, nrow=ncol(x), ncol=nrow(x)))
}
Result:
> w = array(NA,dim=c(4,2))
> t(w[2:4,]) = c(2,3)
> w
[,1] [,2]
[1,] NA NA
[2,] 2 3
[3,] 2 3
[4,] 2 3
Create the matrix row-wise, then assign it:
w[2:4, ] <- matrix(c(2,3), nrow=3, ncol=2, byrow=TRUE)
Another elegant way :-)
w[2:4,] <- rep(c(2,3),each=length(2:4))
[,1] [,2]
[1,] NA NA
[2,] 2 3
[3,] 2 3
[4,] 2 3
w[2:4, ] <- matrix(c(2,3),nrow=1)[ rep(1,3), ]

Resources