Dot product for two matrices in R - 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.

Related

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)

Finding the dimension of a 3D vertex object in 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])
}

Use purrr to get quantile of corresponding matrix entries in a list

I have the following reprex list of 10 sample matrices:
# Sample of 10 3*3 matrices
z1 <- matrix(101:104, nrow = 2, ncol = 2)
z2 <- matrix(201:204, nrow = 2, ncol = 2)
z3 <- matrix(301:304, nrow = 2, ncol = 2)
z4 <- matrix(401:404, nrow = 2, ncol = 2)
z5 <- matrix(501:504, nrow = 2, ncol = 2)
z6 <- matrix(601:604, nrow = 2, ncol = 2)
z7 <- matrix(701:704, nrow = 2, ncol = 2)
z8 <- matrix(801:804, nrow = 2, ncol = 2)
z9 <- matrix(901:904, nrow = 2, ncol = 2)
z10 <- matrix(1001:1004, nrow = 2, ncol = 2)
# Combine all matrices into a single list
za <- list(z1, z2, z3, z4, z5, z6, z7, z8, z9, z10)
What we would like is to take za as an input and obtain 2 2*2 matrices called an upper_quantile and lower_quantile matrices.
Essentially this is to take the above list of 10 matrices and take the upper 97.5% quantile for the corresponding entries. And the same for the lower 2.5% quantile.
In this case we can manually construct the upper_quantile matrix for this example as follows:
upper_quantile <- matrix(data = c(quantile(x = seq(101, 1001, by = 100), probs = 0.975),
c(quantile(x = seq(102, 1002, by = 100), probs = 0.975)),
c(quantile(x = seq(103, 1003, by = 100), probs = 0.975)),
c(quantile(x = seq(104, 1004, by = 100), probs = 0.975)))
, nrow = 2
, ncol = 2
, byrow = FALSE)
upper_quantile
#> [,1] [,2]
#> [1,] 978.5 980.5
#> [2,] 979.5 981.5
I would like to understand how to do this using purrr or tidyverse tools as I have been trying to avoid cumbersome loops on lists and would like to adjust to dimensions automatically.
Could anyone please assist?
Here's a slightly clunky method which at least keeps everything in one pipe. It assumes that all the matrices are the same dimension, which needs to be true else the desired output doesn't make much sense. Working with matrices in purrr is always a little odd. The approach is basically to use flatten to make it easy to group the cells in the order we want, which is one column per location. That lets us map across columns to produce another vector, and then put that vector back into the right matrix. Might need some testing for larger matrices than 2x2.
The other approach I thought about was using cross to make a list of all index combinations, and then mapping through and creating the matrix cell by cell analogous to your example. Can attempt that if desired.
library(tidyverse)
z1 <- matrix(101:104, nrow = 2, ncol = 2)
z2 <- matrix(201:204, nrow = 2, ncol = 2)
z3 <- matrix(301:304, nrow = 2, ncol = 2)
z4 <- matrix(401:404, nrow = 2, ncol = 2)
z5 <- matrix(501:504, nrow = 2, ncol = 2)
z6 <- matrix(601:604, nrow = 2, ncol = 2)
z7 <- matrix(701:704, nrow = 2, ncol = 2)
z8 <- matrix(801:804, nrow = 2, ncol = 2)
z9 <- matrix(901:904, nrow = 2, ncol = 2)
z10 <- matrix(1001:1004, nrow = 2, ncol = 2)
# Combine all matrices into a single list
za <- list(z1, z2, z3, z4, z5, z6, z7, z8, z9, z10)
quant_mat <- function(list, p){
dim = ncol(list[[1]]) * nrow(list[[1]])
list %>%
flatten_int() %>%
matrix(ncol = dim, byrow = TRUE) %>%
as_tibble() %>%
map_dbl(quantile, probs = p) %>%
matrix(ncol = ncol(list[[1]]))
}
quant_mat(za, 0.975)
#> [,1] [,2]
#> [1,] 978.5 980.5
#> [2,] 979.5 981.5
quant_mat(za, 0.025)
#> [,1] [,2]
#> [1,] 123.5 125.5
#> [2,] 124.5 126.5
Created on 2018-03-14 by the reprex package (v0.2.0).
This should do the trick for a single quantile using tidyverse:
tibble(za) %>%
mutate(za = map(za, ~ data.frame(t(flatten_dbl(list(.)))))) %>%
unnest(za) %>%
summarize_all(quantile, probs = .975) %>%
matrix(ncol = 2)

Why is my following matrix statement failing

matrix_1 = matrix(rep(c("p","r"),6), c(rep("control",6), rep("concussion",6)),
nrow = 12, ncol = 2)
It says invalid byrow argument (I want it by column and byrow is F by default) so I basically want the first column to have p and r repeated 6 times for a total of 12 rows and the second column to have Control in first 6 rows and Concussion in the next 6
The usage of matrix is
matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE,
dimnames = NULL)
So, if the data is being split up like in the OP's post, one of the arguments that is not specified would be incorrectly being labelled as byrowi.e. in the OP's code,
data = rep(c("p","r"),6)
The nrow and ncol arguments are specified, leaving the other two arguments in the order to take up the rest of the input i.e.
c(rep("control",6), rep("concussion",6))
would be mistakenly taken as argument for byrow. However, byrow takes a logical argument and it is a potential reason for the error.
matrix_1 = matrix(rep(c("p","r"),6), c(rep("control",6), rep("concussion",6)),
nrow = 12, ncol = 2)
Error in matrix(rep(c("p", "r"), 6), c(rep("control", 6),
rep("concussion", : invalid 'byrow' argument
If we specify the byrow = FALSE, then the error will be based on the dimnames
matrix_1 = matrix(rep(c("p","r"),6), c(rep("control",6), rep("concussion",6)),
nrow = 12, ncol = 2, byrow = FALSE)
Error in matrix(rep(c("p", "r"), 6), c(rep("control", 6),
rep("concussion", : 'dimnames' must be a list
As there is only a single data argument, we need to concatenate the strings
matrix_1 <- matrix(data = c(rep(c("p","r"),6),c(rep("control",6),rep("concussion",6))),
nrow=12,ncol=2)
Now, as byrow = FALSE by default it will not get affected

Resources