I want to replace values in a matrix based on matrix indexes stored in two vectors (one for x, another one for y). I did it some time ago but forgot the syntax for subsetting based on vectors.
Let's say i have this matrix and these 2 arrays:
m <- matrix(0,10,10)
x <- c(1,3,5)
y <- c(2,4,6)
And i need to replace m[1,2], m[3,4], m[5,6] with other value, what would be the syntax in this case? I tried m[x,y] but doesn't work.
Without sparse matrix support:
If we include z <- c(4.5,5.6,6.7) for the values then,
for(i in 1:length(z)) m[x[i],y[i]] <- z[i]
If you want to an apply solution, this is all I could think of,
apply(data.frame(x=x,y=y,z=z),1,function(row) .GlobalEnv$m[row[1],row[2]] <- row[3])
I remembered how it was, to subset a matrix from vectors the syntax is:
m[cbind(x,y)]
Related
df<- data.frame(a=c(1:10), b=c(21:30),c=c(1:10), d=c(14:23),e=c(11:20),f=c(-6:-15),g=c(11:20),h=c(-14:-23),i=c(4:13),j=c(1:10))
In this data frame, I have three block-diagonal matrices which are as shown in the image below
I want to apply two functions, one is the sine function for block diagonal and the second is cosine function for the other elements and generates the same structure of the data frame.
sin(df[1:2,1:2])
sin(df[3:5,3:5])
sin(df[6:10,6:10])
cos(the rest of the elements)
1) outer/arithmetic Create a logical block diagonal matrix indicating whether the current cell is on the block diagonal or not and then use that to take a convex combination of the sin and cos values giving a data.frame as follows:
v <- rep(1:3, c(2, 3, 5))
ind <- outer(v, v, `==`)
ind * sin(df) + (!ind) * cos(df)
2) ifelse Alternately, this gives a matrix result (or use as.matrix on the above). ind is from above.
m <- as.matrix(df)
ifelse(ind, sin(m), cos(m))
3) Matrix::bdiag Another approach is to use bdiag in the Matrix package (which comes with R -- no need to install it).
library(Matrix)
ones <- function(n) matrix(1, n, n)
ind <- bdiag(ones(2), ones(3), ones(5)) == 1
Now proceed as in the last line of (1) or as in (2).
If it's okay for you that the result is stored in a new data frame you could change the order of your instructions and do it like that:
ndf <- cos(df)
ndf[1:2,1:2] <- sin(df[1:2,1:2])
ndf[3:5,3:5] <- sin(df[3:5,3:5])
ndf[6:10,6:10] <- sin(df[6:10,6:10])
Consider the data frame:
set.seed(1234)
n = 10
dat <- data.frame(x=runif(n,0,200), d=rbinom(n,1,.5))
Now I want to crate a matrix a with n by n dimension whose element a[i,j]=1 , if (dat[j,1]==x[i]& dat[j,2]==1), and 0 otherwise.
The following codes work correctly:
a <- matrix(,ncol=n, nrow=n)
for(i in 1:n){
a[i,] <- (dat$x==dat$x[i] & dat$d==1)
}
But is there a way to create the a variable with outer() or similar other function?
You could use diag(), to convert dat$x to the diagonal of a matrix. We add the logical condition "==1" to turn the binary matrix into a boolean one.
diag(dat$d)==1
Here is another vectorized option
a <- matrix(FALSE,ncol=n, nrow=n)
a[row(a)==col(a)] <- dat$d==1
I am a newbie to R, but avid to learn.
I have been trying endlessly to create a matrix with a variable element (in this case [2,2]). The variable element should take number 4 on the first run and 5 on the second (numbers).
This matrix would be multiplied by another matrix (N0) and produce a result matrix (resul).
Up so far, I have only been able to create the initial matrix with the variable element using a for loop, but I am having problems indexing the result matrix. I have tried several versions, but this is the latest. Any suggestions would be greatly appreciated. Thank you.
numbers <- c(4,5,length.out = 2)
A <- matrix(c(1,2,3,NA),nrow=2,ncol=2)
resul <- matrix(nrow=2,ncol=1)
for (i in 1:2) {
A[2,2]<- matrix(numbers[i])
N0 <- matrix(c(1,2),nrow=2,ncol=1)
resul[i,]<- A[i,i]%*%N0
}
Your code has two distinct problems. the first is that A[i,i] is a 1 x 1
matrix, so you're getting an error because your multiplying a 1 x 1 matrix
by a 2 x 1 matrix (N0).
you could either drop the subscript [i,i] and initialize the result to be
a two by two matrix like so:
result <- matrix(nrow=2,ncol=1)
for (i in 1:2){
A[2,2]<- matrix(numbers[i])
# a colunm vector
N0 <- matrix(c(1,2),
nrow=2,
ncol=1)
# note the index is on the column b/c `A%*%N0` is a column matrix
result[,i]<- A%*%N0
}
or you could either drop the the second subscript [i,] and initialize the result to be
a two by two matrix like so:
result <- matrix(nrow=2,ncol=1)
for (i in 1:2){
A[2,2]<- matrix(numbers[i])
# a colunm vector
N0 <- matrix(c(1,2),
nrow=2,
ncol=1)
result[i,]<- A[i,]%*%N0
}
but it's not clear from you post which (if either) answer is the correct one. Indexing is tricky :)
I have following problem with R function findInterval()
Given a vector X and a matrix Y, I want to find in which interval lie elements of X. Intervals are constructed, having breakpoints in Y rows. In other words for X = c(2,3) and Y = matrix(c(3,1,4,2,5,4),2,3), the output would be c(0,2). I wrote following code:
X <- c(2,3)
Y <- matrix(c(3,1,4,2,5,4),2,3)
output <- diag(apply(Y,1,function(z)findInterval(X,z)))
and it works. However, I think, it can be optimised, since the apply function returns 2 x 2 matrix (that's why i had to get diagonal of that). Is there a way to do the same, but using function, which will return a vector, taking as an argument my vector X and matrix Y? I perform this operation on high-demensional vectors, so obtaining unnecessary matrixes size 10000 x 10000 is not a good idea imho. To maximize efficiency, I don't want to use loops.
Thanks in advance for any feedback.
You can do
rowSums(X > Y)
# [1] 0 2
I have a large-ish dataframe (40000 observations of 800 variables) and wish to operate on a range of columns of every observation with something akin to dot product. This is how I implemented it:
matrixattempt <- as.matrix(dframe)
takerow <- function(k) {as.vector(matrixattempt[k,])}
takedot0 <- function(k) {sqrt(sum(data0averrow * takerow(k)[2:785]))}
for (k in 1:40000){
print(k)
dframe$dot0aver[k]<-takedot0(k)
}
The print is just to keep track of what's going on. data0averrow is a numeric vector, same size as takerow(k)[2:785], that has been pre-defined.
This is running, and from a few tests running correctly, but it is very slow.
I searched for dot product for a subset of columns, and found this question, but could not figure out how to apply it to my setup. ddply sounds like it should work faster (although I do not want to do splitting and would have to use the same define-id trick that the referenced questioner did). Any insight/hints?
Try this:
sqrt(colSums(t(matrixattempt[, 2:785]) * data0averrow))
or equivalently:
sqrt(matrixattempt[, 2:785] %*% data0averrow)
Use matrix multiplication and rowSums on the result:
dframe$dot0aver <- NA
dframe$dot0aver[2:785] <- sqrt( rowSums(
matrixattempt[2:785,] %*% data0averrow ))
It's the sqrt of the dot-product of data0aver with each row in the range