Finding the dimension of a 3D vertex object in R - r

Is there a way to find the dimension of an 3D object (face) in R defined by a set of vertices (the object is the convex hull of the vertices). That is, defining the function getDim().
vertices<-matrix(c(1,1,1,1,1,1), ncol = 3, byrow = TRUE)
getDim(vertices) # should return 0
vertices<-matrix(c(0,0,0,1,1,1,2,2,2,3,3,3), ncol = 3, byrow = TRUE)
getDim(vertices) # should return 1
vertices<-matrix(c(0,0,0,0,1,1,0,2,2,0,0,2), ncol = 3, byrow = TRUE)
getDim(vertices) # should return 2
vertices<-matrix(c(0,0,0,0,1,1,0,2,2,0,0,2,1,1,1), ncol = 3, byrow = TRUE)
getDim(vertices) # should return 3

Thanks to Stephane Laurent for a hint
getDim3D<-function(points) {
x <- unique(points)
if (dim(x)[1]==1) return(0)
x <- x[2:dim(x)[1],,drop=F] - matrix(rep(x[1,], times = dim(x)[1]-1), ncol = dim(x)[2], byrow = TRUE)
return(Matrix::rankMatrix(x)[1])
}

Related

Dot product for two matrices in R

How do I compute the dot product for
movies <- matrix(c(3,1,1,2,1,4,3,1,1,3), ncol = 2, byrow = T)
users <- matrix(c(1,0,0,1,1,0,1,1), ncol = 2, byrow = T)
expected <- matrix(c(3,1,1,3,1,
1,2,4,1,3,
3,1,1,3,1,
4,3,5,4,4), ncol = 5, byrow = T)
This example is from
https://www.youtube.com/watch?v=ZspR5PZemcs
at 12:55
Answer is
users %*% t(movies)
I have been confused by "dot product" I think this is something different from matrix multiplication.

Is there a way to generate a function where the object name changes with the input of the function?

Something as such:
gen_sigma <- function(i) {
sigma_`i` <- matrix(c(1, i, i, 1), nrow = 2, byrow = TRUE)
}
The 'right' thing to do is to use a list as follows, rather than polluting your environment with lots of variable names. This is an example:
n = 10
res_list = vector(length = n, mode = 'list')
for (i in 1:n) {
res_list[[i]] = matrix(c(1, i, i, 1), nrow = 2, byrow = TRUE)
}
or using lapply
n = 10
res_list = lapply(1:n, function(x) matrix(c(1, x, x, 1), nrow = 2, byrow = TRUE))
One other option is to use assign and get, although I would hope there is a cleaner solution than this, as using these functions is often a bit of a code-smell. I think putting it into a list would likely be the best solution.
gen_sigma <- function(i) {
output_name = paste0("sigma_", i)
assign(output_name, matrix(c(1, i, i, 1), nrow = 2, byrow = TRUE), envir=parent.frame())
get(output_name)
}
gen_sigma(5)
> sigma_5
[,1] [,2]
[1,] 1 5
[2,] 5 1

Finding index of array of matrices, that is closest to each element of another matrix in R

I have an array Q which has size nquantiles by nfeatures by nfeatures. In this, essentially the slice Q[1,,] would give me the first quantile of my data, across all nfeatures by nfeatures of my data.
What I am interested in, is using another matrix M (again of size nfeatures by nfeatures) which represents some other data, and asking the question to which quantile do each of the elements in M lie in Q.
What would be the quickest way to do this?
I reckon I could do double for loop across all rows and columns of the matrix M and come up with a solution similar to this: Finding the closest index to a value in R
But doing this over all nfeatures x nfeatures values will be very inefficient. I am hoping that there might exist a vectorized way of approaching this problem, but I am at a lost as to how to approach this.
Here is a reproducible way of the slow way I can approach the problem with O(N^2) complexity.
#Generate some data
set.seed(235)
data = rnorm(n = 100, mean = 0, sd = 1)
list_of_matrices = list(matrix(data = data[1:25], ncol = 5, nrow = 5),
matrix(data = data[26:50], ncol = 5, nrow = 5),
matrix(data = data[51:75], ncol = 5, nrow = 5),
matrix(data = data[76:100], ncol = 5, nrow = 5))
#Get the quantiles (5 quantiles here)
Q <- apply(simplify2array(list_of_matrices), 1:2, quantile, prob = c(seq(0,1,length = 5)))
#dim(Q)
#Q should have dims nquantiles by nfeatures by nfeatures
#Generate some other matrix M (true-data)
M = matrix(data = rnorm(n = 25, mean = 0, sd = 1), nrow = 5, ncol = 5)
#Loop through rows and columns in M to find which index of the array matches up closest with element M[i,j]
results = matrix(data = NA, nrow = 5, ncol = 5)
for (i in 1:nrow(M)) {
for (j in 1:ncol(M)) {
true_value = M[i,j]
#Subset Q to the ith and jth element (vector of nqauntiles)
quantiles = Q[,i,j]
results[i,j] = (which.min(abs(quantiles-true_value)))
}
}
'''

Plotting 3D Network

I have a series of points that exist in 3 dimensional space (x, y, and z) and an adjacency matrix that determines connections between those points (see example below). How would I plot that? Thanks!
points = matrix(c(2,3,2, 5,4,9, 4,1,8), byrow = TRUE, ncol = 3) #each row is a point and the colums are x, y, and z respectively
adj_mat = matrix(c(0,1,0, 1,0,1, 0,1,0), byrow = TRUE, ncol = 3)
There may be a more elegant way to handle the adjacency matrix, but as far as I can tell rgl::segments3d() turns sequential points into segments, so you need to repeat points for each connection. The below approach is slightly redundant; set the upper or lower triangle to 0 if you like, but you won't be able to see the difference anyway since the segments will overplot.
points = matrix(
c(2,3,2, 5,4,9, 4,1,8),
byrow = TRUE, ncol = 3,
dimnames = list(NULL, c('x', 'y', 'z'))
)
adj_mat = matrix(c(0,1,0, 1,0,1, 0,1,0), byrow = TRUE, ncol = 3)
segments <- points[as.vector(matrix(
c(row(points)[as.logical(adj_mat)],
col(points)[as.logical(adj_mat)]),
byrow = TRUE, nrow = 2
)), ]
library(rgl)
plot3d(points)
segments3d(segments)

summing matrices that are inside objects in r

I have a list of objects. Each object has a matrix. I would like to perform matrix summation over all objects. Currently, I do it by combining "Reduce" and "lapply", where lapply takes a function that extracts the matrix from each object.
Is there a more efficient way to implement this?
Dummy example:
mat_1 = matrix(data = c(rep(0.01,4),rep(0.29,4)), nrow = 4, ncol = 2)
mat_2 = matrix(data = c(rep(0.1,4),rep(0.2,4)), nrow = 4, ncol = 2)
obj_1 = list(name = "obj1", my_mat = mat_1) class(obj_1) = "my_obj"
obj_2 = list(name = "obj2", my_mat = mat_2) class(obj_2) = "my_obj"
list_of_my_objs = list(obj_1,obj_2)
get_mat_from_obj = function(my_obj) {
return(my_obj$my_mat)
}
Reduce('+', lapply(list_of_my_objs,get_mat_from_obj))

Resources