Place a vector randomly inside a matrix in R - 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

Related

Number of rows with exactly 1 numerical value in matrice (R)

I have a matrice that is as such:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 0 0 0 0 0 0 0 0 0
[2,] 0 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0 0
[4,] 0 0 0 0 0 0 0 1 1
[5,] 0 0 0 0 0 0 1 1 0
[6,] 0 0 0 0 0 1 0 0 0
[7,] 0 0 0 0 1 1 0 0 0
[8,] 0 0 0 0 1 0 0 0 0
[9,] 0 0 0 0 1 0 0 0 0
[10,] 0 0 0 0 1 1 0 0 0
[11,] 0 0 0 0 0 1 0 0 0
[12,] 0 0 0 0 0 1 1 1 1
[13,] 0 0 0 0 0 0 0 0 0
[14,] 0 0 0 0 0 0 0 0 0
[15,] 0 0 0 0 0 0 0 0 0
[16,] 0 0 0 0 0 0 0 0 0
[17,] 0 0 0 0 0 0 0 0 0
[,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17]
[1,] 0 0 0 0 0 0 0 0
[2,] 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0
[4,] 1 1 0 0 0 0 0 0
[5,] 0 1 0 0 0 0 0 0
[6,] 0 1 0 0 0 0 0 0
[7,] 0 1 0 0 0 0 0 0
[8,] 0 1 0 0 0 1 0 0
[9,] 0 1 0 0 0 1 0 0
[10,] 1 1 0 0 0 1 0 0
[11,] 1 1 0 1 1 0 0 0
[12,] 1 1 1 1 0 0 0 0
[13,] 0 0 0 0 0 0 0 0
[14,] 0 0 0 0 0 0 0 0
[15,] 0 0 0 0 0 0 0 0
[16,] 0 0 0 0 0 0 0 0
[17,] 0 0 0 0 0 0 0 0
[,18]
[1,] 0
[2,] 0
[3,] 0
[4,] 0
[5,] 0
[6,] 0
[7,] 0
[8,] 0
[9,] 0
[10,] 0
[11,] 0
[12,] 0
[13,] 0
[14,] 0
[15,] 0
[16,] 0
[17,] 0
How can I count the number of rows with exactly 1 value, not more than one?
I've tried using nrow(imageMatrix[imageMatrix < 2])
and also tried converting the matrice to dataframe and then using nrow(dataframe_matrice[dataframe_matrice == 1,])
but it has been of no avail.
Here imageMatrix is the name of the matrice.
Can someone please offer me a hint on what I'm doing wrong with my first line of code in counting rows?
We may use rowSums on a logical matrix (imageMatrix == 1) and then create a logical vector == 1 and get the count with sum
sum(rowSums(imageMatrix == 1) == 1)
imageMatrix <2 is a logical matrix, when it is used to subset the original matrix, it returns a vector of values which doesn't have dim and thus nrow wouldn't work i.e.
nrow(1:5)
NULL

Uniqe ID in list of indexed 2D/3D Image masks (or 2D/3D matrix) in R [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I want to make a "global" ID of 2D/3D nuclear masks across a list of images.
When i segment my cells they are numbered from 1:numberOfCellsInEachImage. but I would like to have an uniqe Id for each cells across all images.
I have already tried to make a forloop with a global counter and assigned IDs acording to the counter, but It became a messy large thing that I do not trust compleatly
# minimal exampe
img1 = matrix(data = 0, nrow = 15, ncol = 15)
img1[2:3, 2:3] = 1
img1[9:10, 5:6] = 2
img1[2:4, 11:13] = 3
img1
# Example indexed image 1
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15]
# [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [2,] 0 1 1 0 0 0 0 0 0 0 3 3 3 0 0
# [3,] 0 1 1 0 0 0 0 0 0 0 3 3 3 0 0
# [4,] 0 0 0 0 0 0 0 0 0 0 3 3 3 0 0
# [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [9,] 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0
#[10,] 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0
#[11,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#[12,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#[13,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#[14,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#[15,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
img2 = matrix(data = 0, nrow = 15, ncol = 15)
img2[3:4, 2:4] = 1
img2[10:11, 5:7] = 2
img2[3:5, 11:14] = 3
img2
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15]
# [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [3,] 0 1 1 1 0 0 0 0 0 0 3 3 3 3 0
# [4,] 0 1 1 1 0 0 0 0 0 0 3 3 3 3 0
# [5,] 0 0 0 0 0 0 0 0 0 0 3 3 3 3 0
# [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [9,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#[10,] 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0
#[11,] 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0
#[12,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#[13,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#[14,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#[15,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# This is the data structure I have
#
listOfImages2D = list(img1, img2)
#x = listOfImages2D[[1]]
listOfImages3D = lapply(listOfImages2D, function(x){
x_out = array(data = 0, dim = c(15, 15, 3) )
x_out[,,2] = x
return(x_out)
})
#What I want
# I want all numbers to become an uniqe ID across images
# All zeros should remain zero
# I use img1[img1 == 0 ] = 0 #after giving uniqe IDs
# Image one should ideally start at 1
# ## desired output
# listOfImages2D_global_index[[1]]
# # same as above
#
# listOfImages2D_global_index[[2]]
# # [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15]
# # [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# # [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# # [3,] 0 4 4 4 0 0 0 0 0 0 6 6 6 6 0
# # [4,] 0 4 4 4 0 0 0 0 0 0 6 6 6 6 0
# # [5,] 0 0 0 0 0 0 0 0 0 0 6 6 6 6 0
# # [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# # [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# # [8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# # [9,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# #[10,] 0 0 0 0 5 5 5 0 0 0 0 0 0 0 0
# #[11,] 0 0 0 0 5 5 5 0 0 0 0 0 0 0 0
# #[12,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# #[13,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# #[14,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# #[15,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#
# # the code should also work for 3 dimensions
Something like this? It's a little crude in that not every successive index is used (7 is skipped in this case), but the relative difference between values within each array is maintained, which might be useful. If you want to use every index, that wouldn't be too difficult, but would slow down processing.
z <- 0 # need this to initiate the loop
a <- c(0, 0, 1, 1, 0, 0, 2, 2, 0, 3, 3, 3)
b <- c(0, 3, 3, 3, 0, 2, 2, 2, 0, 0, 0, 0)
g <- c(1, 1, 1, 1, 0, 0, 3, 3, 0, 0, 0, 0)
l <- list(z=z, a=a, b=b, g=g)
# l[-1] <- lapply(l[-1], `dim<-`, c(2, 6)) # 2D
# l[-1] <- lapply(l[-1], `dim<-`, c(2, 2, 3)) # 3D
for (i in 2:length(l)) {
lnz <- l[[i]] != 0
# l[[i]][lnz] <- as.numeric(factor(l[[i]][lnz])) # force successive
d <- max(l[[i-1]]) - min(l[[i]][lnz])
l[[i]][lnz] <- l[[i]][lnz] + d + 1
}
l[-1]
# $a
# [1] 0 0 1 1 0 0 2 2 0 3 3 3
#
# $b
# [1] 0 5 5 5 0 4 4 4 0 0 0 0
#
# $g
# [1] 6 6 6 6 0 0 8 8 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

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

add a value randomly to a matrix

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

Resources