add a value randomly to a matrix - r

How can I randomly add a value to a matrix?
say I have:
mat <- matrix(0, 10, 10)
v = 5
how can I add randomly v to mat, 2 positions at a time? The output should look like this after a single iteration:
out
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 0 0 0 0 0 0 0 0
[2,] 5 0 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0 0 0
[4,] 0 0 0 0 5 0 0 0 0 0
[5,] 0 0 0 0 0 0 0 0 0 0
[6,] 0 0 0 0 0 0 0 0 0 0
[7,] 0 0 0 0 0 0 0 0 0 0
[8,] 0 0 0 0 0 0 0 0 0 0
[9,] 0 0 0 0 0 0 0 0 0 0
[10,] 0 0 0 0 0 0 0 0 0 0
After another iteration, mat should have 2 more positions filled with the value in 'v'

You could use ?sample to randomly index your matrix:
idx <- sample(length(mat), size=2)
mat[idx] <- mat[idx] + v

Related

How can I change some element of matrix inside a function in R language automatically?

I have tried to write a function for this part of code and I can not mange because I am new to R
can someone help me?
I made a function like this :
m <- matrix(0, nrow=10, ncol=10) # Create an adjacency matrix
and I have changed the the element of it like below :
m[1,2] <- m[2,3] <- m[3,4] <-m[4,5]<-m[5,6]<-m[6,7]<-m[7,8] <-m[8,9]<-m[9,10]<-m[1,10] <- 1
but how can i do it automatically inside a function? to automatically iterate and change value?
I am not very sure about the logic for why m[1,10] is assigned one, for the others, you can do:
m <- matrix(0, nrow=10, ncol=10)
m[row(m) == col(m)-1] <- 1
m
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 1 0 0 0 0 0 0 0 0
[2,] 0 0 1 0 0 0 0 0 0 0
[3,] 0 0 0 1 0 0 0 0 0 0
[4,] 0 0 0 0 1 0 0 0 0 0
[5,] 0 0 0 0 0 1 0 0 0 0
[6,] 0 0 0 0 0 0 1 0 0 0
[7,] 0 0 0 0 0 0 0 1 0 0
[8,] 0 0 0 0 0 0 0 0 1 0
[9,] 0 0 0 0 0 0 0 0 0 1
[10,] 0 0 0 0 0 0 0 0 0 0

Place a vector randomly inside a matrix in R

How can I place the vector a<-c(1,2,3,4,5,6) in a ramdom position in the matrix m<-matrix(0, nrow = 10, ncol = 10)?
The vector has to be together:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 0 0 0 0 0 0 0 0
[2,] 1 0 0 0 0 0 0 0 0 0
[3,] 2 0 0 0 0 0 0 0 0 0
[4,] 3 0 0 0 0 0 0 0 0 0
[5,] 4 0 0 0 0 0 0 0 0 0
[6,] 5 0 0 0 0 0 0 0 0 0
[7,] 6 0 0 0 0 0 0 0 0 0
[8,] 0 0 0 0 0 0 0 0 0 0
[9,] 0 0 0 0 0 0 0 0 0 0
[10,] 0 0 0 0 0 0 0 0 0 0
And it has to be horizontally, vertically or diagonally
I have tried:
start = sample.int(length(m), 1)
m[start:(start+length(a)-1)] = a
But it cannot take place the following:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 0 0 0 0 5 0 0 0
[2,] 0 0 0 0 0 0 6 0 0 0
[3,] 0 0 0 0 0 0 0 0 0 0
[4,] 0 0 0 0 0 0 0 0 0 0
[5,] 0 0 0 0 0 0 0 0 0 0
[6,] 0 0 0 0 0 0 0 0 0 0
[7,] 0 0 0 0 0 1 0 0 0 0
[8,] 0 0 0 0 0 2 0 0 0 0
[9,] 0 0 0 0 0 3 0 0 0 0
[10,] 0 0 0 0 0 4 0 0 0 0
Thanks
Sample a 1d index of the same size as a and then assign the vector to m at those indices:
m[sample.int(length(m), length(a))] <- a
m
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 0 6 0 0 0 0 0 0 0 0
# [2,] 0 0 0 0 0 4 0 0 0 0
# [3,] 0 3 0 1 0 0 0 0 5 0
# [4,] 0 0 0 0 0 0 0 0 0 0
# [5,] 0 0 0 0 0 0 0 0 0 0
# [6,] 0 0 0 0 0 0 0 0 0 0
# [7,] 0 0 0 0 0 0 0 0 0 0
# [8,] 0 0 0 0 0 0 0 0 2 0
# [9,] 0 0 0 0 0 0 0 0 0 0
#[10,] 0 0 0 0 0 0 0 0 0 0
If the vector needs to be continuous, you can sample the start index, and then assign with range index:
start = sample.int(length(m), 1)
m[start:(start+length(a)-1)] = a
m
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 0 0 0 0 0 0 0 0 0 0
# [2,] 0 0 0 0 0 0 0 0 0 0
# [3,] 0 0 0 0 0 0 0 0 0 0
# [4,] 0 0 0 0 0 0 0 0 0 0
# [5,] 1 0 0 0 0 0 0 0 0 0
# [6,] 2 0 0 0 0 0 0 0 0 0
# [7,] 3 0 0 0 0 0 0 0 0 0
# [8,] 4 0 0 0 0 0 0 0 0 0
# [9,] 5 0 0 0 0 0 0 0 0 0
#[10,] 6 0 0 0 0 0 0 0 0 0

How to iteratively fill a matrix with rnorm values using a for loop?

I have a question, I am trying to create a 10x10 matrix using the code below, where the first column contains 10 values from a normal distribution with std dev of .5 and a mean equal to j where j is a value 1:10. My code below produces the observed matrix, where only the final column is filled with values. What am I doing wrong? Thank you.
for(j in 1:10){
y<-matrix(0,ncol=10,nrow=10)
y[,j]<-rnorm(n=10,mean=j,sd=.5)
}
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 0 0 0 0 0 0 0 10.857520
[2,] 0 0 0 0 0 0 0 0 0 10.490549
[3,] 0 0 0 0 0 0 0 0 0 9.888620
[4,] 0 0 0 0 0 0 0 0 0 9.495205
[5,] 0 0 0 0 0 0 0 0 0 9.674356
[6,] 0 0 0 0 0 0 0 0 0 10.810197
[7,] 0 0 0 0 0 0 0 0 0 10.337517
[8,] 0 0 0 0 0 0 0 0 0 9.715229
[9,] 0 0 0 0 0 0 0 0 0 9.902603
[10,] 0 0 0 0 0 0 0 0 0 8.972656

emd2d function from emdist segfaults

I'm trying to apply a function to a list using apply but I'm having trouble doing so. I'm trying to calculate the earth-movers distance using the emdist package. Every index in the list has two subindices. I want to calculate the earth-movers distance for these subindices iteratively (the real list has thousands of indices). The problem is Rstudio crashes each time I try to run the code on a test dataset. An example of the test dataset:
set.seed(42)
output1 <- list(list(matrix(0,8,11),matrix(0,8,11)), list(matrix(rnorm(80),8,10),matrix(rnorm(80),8,10)))
[[1]]
[[1]][[1]]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,] 0 0 0 0 0 0 0 0 0 0 0
[2,] 0 0 0 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0 0 0 0
[4,] 0 0 0 0 0 0 0 0 0 0 0
[5,] 0 0 0 0 0 0 0 0 0 0 0
[6,] 0 0 0 0 0 0 0 0 0 0 0
[7,] 0 0 0 0 0 0 0 0 0 0 0
[8,] 0 0 0 0 0 0 0 0 0 0 0
[[1]][[2]]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,] 0 0 0 0 0 0 0 0 0 0 0
[2,] 0 0 0 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0 0 0 0
[4,] 0 0 0 0 0 0 0 0 0 0 0
[5,] 0 0 0 0 0 0 0 0 0 0 0
[6,] 0 0 0 0 0 0 0 0 0 0 0
[7,] 0 0 0 0 0 0 0 0 0 0 0
[8,] 0 0 0 0 0 0 0 0 0 0 0
Now when I do this:
library(emdist)
sapply(output1,function(x) {emd2d(x[[seq_along(x)[1]]],x[[seq_along(x)[2]]]) })
Rstudio simply crashes. I have also tried:
mapply(emd2d,sapply(output1,`[`,1),sapply(output1,`[`,2))
But to no avail. Any ideas? I'm running this on a 2013 macbook air with 2gb of RAM.
this works fine:
> emd2d(output1[[2]][[1]],output1[[2]][[2]])
[1] -6.089909
this does not:
emd2d(output1[[1]][[1]],output1[[1]][[2]])
Seems emd2d() might hate it when you compare two all zero matrices...
At least for me on OSX as this succeeds for me:
set.seed(666)
output2 <- list(list(matrix(5,8,11),matrix(5,8,11)),
list(matrix(rnorm(80),8,10),matrix(rnorm(80),8,10)))
sapply(output2,function(x) {emd2d(x[[1]],x[[2]]) })
#[1] 0.000000 -7.995288
# not i removed your seq_along because I don't think you really want this..
as does this:
> set.seed(666)
> output2 <- list(list(matrix(0,8,11),matrix(5,8,11)), list(matrix(rnorm(80),8,10),matrix(rnorm(80),8,10)))
> sapply(output2,function(x) {emd2d(x[[1]],x[[2]]) })
[1] NaN -7.995288
Maybe you need to contact the package creator about this then, in the mean time you could create a function that checks if both matrices are all zeros, e.g.
foo <- function(z){ if( sum(length(z[[1]][ z[[1]] != 0]),
length(z[[2]][ z[[2]] != 0]) ) > 0){
emd2d(z[[1]],z[[2]])
}else{
0
}
}
# i use length and subsetting, not just sum(), in case somehow
# the two matrices sum to zero because you have minus values in them
> sapply(output1, foo)
[1] 0.000000 -6.089909

Find a path or route in R

So here is a matrix A which shows if point 1 to 10 is connected with each other. 1 means they are connected and 0 means they are not. I would like to find out if there is a path from one point to the other. Let's say the start point is 1 and the end point is 3. The number of points involved in between doesn't matter. Points can be used repeatedly. I just want to know if 1 can reach 3. How can I do this?
From what we can see, one of the possible paths is 1-8-6-2-3. But how to do it with R? Thanks a lot. Any help is appreciated.
A
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 0 0 0 0 0 1 0 0
[2,] 0 0 1 0 1 1 0 0 0 0
[3,] 0 1 0 0 0 0 0 0 0 0
[4,] 0 0 0 0 0 0 0 1 0 0
[5,] 0 1 0 0 0 0 0 0 0 0
[6,] 0 1 0 0 0 0 1 1 0 0
[7,] 0 0 0 0 0 1 0 0 0 1
[8,] 1 0 0 1 0 1 0 0 0 0
[9,] 0 0 0 0 0 0 0 0 0 0
[10,] 0 0 0 0 0 0 1 0 0 0
For this task I think that igraph will make your life easier
require(igraph)
dat <- read.table(text =
'0 0 0 0 0 0 0 1 0 0
0 0 1 0 1 1 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 1 1 0 0
0 0 0 0 0 1 0 0 0 1
1 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0', header = FALSE)
dat <- as.matrix(dat)
g <- graph.adjacency(dat, mode = "undirected")
get.shortest.paths(g, 1, 3)
## [[1]]
## [1] 1 8 6 2 3
If you just want to test if a path exist you can create your own function like this one
test_paths <- function(g, from, to, ...) {
is.finite(c(shortest.paths(g, from, to, ...)))
}
test_paths(g, 1, 9)
## [1] FALSE
test_paths(g, 1, 8)
## [1] TRUE
The idea behind this code is simple : shortest.path return Inf when there's no path between two node (and the path length when it exists) so we can just test whether the number returned is finite (is.finite).
You can do this by repetitive matrix multiplication, until the matrix stays the same:
# generate symetric matrix
set.seed(123)
m <- matrix(rbinom(100, 1, 0.2), nrow = 10)
m <- m * upper.tri(m)
m <- m + t(m)
m0 <- m
m0
Generated matrix:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 1 1 1 0 0 0 0 0 0
[2,] 1 0 0 1 0 0 0 0 0 0
[3,] 1 0 0 0 0 0 0 0 0 0
[4,] 1 1 0 0 0 0 0 0 0 0
[5,] 0 0 0 0 0 0 1 0 0 0
[6,] 0 0 0 0 0 0 0 0 0 0
[7,] 0 0 0 0 1 0 0 0 1 0
[8,] 0 0 0 0 0 0 0 0 1 0
[9,] 0 0 0 0 0 0 1 1 0 0
[10,] 0 0 0 0 0 0 0 0 0 0
Now multiply, until its stabilized:
m <- m0
while (TRUE) {
new_m <- sign(m + m %*% m)
if (all(new_m == m))
break;
m <- new_m
}
m
The resultant matrix contains 1 if there is a path between those nodes:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 1 1 1 0 0 0 0 0 0
[2,] 1 1 1 1 0 0 0 0 0 0
[3,] 1 1 1 1 0 0 0 0 0 0
[4,] 1 1 1 1 0 0 0 0 0 0
[5,] 0 0 0 0 1 0 1 1 1 0
[6,] 0 0 0 0 0 0 0 0 0 0
[7,] 0 0 0 0 1 0 1 1 1 0
[8,] 0 0 0 0 1 0 1 1 1 0
[9,] 0 0 0 0 1 0 1 1 1 0
[10,] 0 0 0 0 0 0 0 0 0 0

Resources