Create a matrix with vector (not scalar) elements - r

I want to create an object like a matrix with vectors for its elements. like:
(1,2,3) (1,3,6) (2,4,1)
(0,7,8) (2,3,4) (5,2,1)
(9,0,8) (8,4,6) (1,1,1)
What should I do?

You can use a matrix list. Initially you create a list of vectors:
vec <- list(1:3, 4:10, 2:5, letters[1:3])
then coerce it to a matrix:
mat1 <- matrix(vec, nrow = 2, ncol = 2)
# [,1] [,2]
#[1,] integer,3 integer,4
#[2,] integer,7 character,3
mat2 <- matrix(vec, nrow = 2, ncol = 2, byrow = TRUE)
# [,1] [,2]
#[1,] integer,3 integer,7
#[2,] integer,4 character,3
To extract its elements, use for example:
mat1[1, 1][[1]]
The first [1, 1] is getting matrix element. But since an element is a list, use an extra [[1]] to access the actual vector.
If you want to see its contents when printing it, then coerce it to a data frame instead. For example,
dat1 <- data.frame(mat1)
# X1 X2
#1 1, 2, 3 2, 3, 4, 5
#2 4, 5, 6, 7, 8, 9, 10 a, b, c
You can change column names later, like,
names(dat1) <- c("col1", "col2")
# col1 col2
#1 1, 2, 3 2, 3, 4, 5
#2 4, 5, 6, 7, 8, 9, 10 a, b, c
Accessing its columns by dat1$col1, dat1[[1]] or dat1[["col1"]]. In this case, each column is a list.
If your end goal is a data frame not a matrix, you can construct this data frame directly, but has to protect each column with I():
data.frame(col1 = I(list(1:3, 4:10)),
col2 = I(list(2:5, letters[1:3])) )
# col1 col2
#1 1, 2, 3 2, 3, 4, 5
#2 4, 5, 6,.... a, b, c
Anyway, I don't like these data structures. It potentially make further operation cumbersome.

Related

Slicing high-dimensional R arrays with index pairs

For the matrix M <- matrix(1:24, nrow = 6, ncol = 4), if you want to subset its elements by the index pairs, which are stored as rows in matrix indexes <- cbind(1:3, 2:4), you can do:
M[indexes]
# [1] 7 14 21
However, I haven't found a simple way to combine index pairs and index grids in slicing higher-dimensional arrays. For example, we have the array A <- array(1:24, dim = c(2,3,4), of which the first dimension should be kept and the last two dimensions are to be subsetted by index pairs. A wordy solution might be:
sapply(1:nrow(indexes), \(i) A[, indexes[i,1], indexes[i,2]])
# and structure the matrix back to the array form, if A has even higher dimension.
# [,1] [,2] [,3]
# [1,] 7 15 23
# [2,] 8 16 24
But I still want something as clean as
A[, indexes[,1], indexes[,2], pairwise = TRUE] # does it exist?
Update 1
Moreover, I have checked what the Numpy in Python has for their arrays, and I found the following example from this site:
X = np.arange(12).reshape((3, 4))
X
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
row = np.array([0, 1, 2])
col = np.array([2, 1, 3])
X[row, col]
# array([ 2, 5, 11])
X[row[:, np.newaxis], col] # broadcasting rules
# array([[ 2, 1, 3],
# [ 6, 5, 7],
# [10, 9, 11]])
The python version of the solution is quite simple and clear. In the same spirit,

Find out if input is a Toeplitz Matrix in R

Given a random matrix (any size!), write a function that determines whether or not that matrix is a Toeplitz Matrix. In linear algebra, a Toeplitz matrix is one in which the elements on any given diagonal from top left to bottom right are identical.
Here is an example:
x <- structure(c(1, 5, 4, 7, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 8,
4, 3, 2), .Dim = 4:5)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 8
[2,] 5 1 2 3 4
[3,] 4 5 1 2 3
[4,] 7 4 5 1 2
So our function should receive such matrix and return TRUE if it meets the conditions.
To test the function, one can use stats::toeplitz() to generate a toeplitz matrix. So for example, the expected output of our function should be:
> toeplitz_detector(stats::toeplitz(sample(5, 5)))
> [1] TRUE
I've solved the problem by defining the following function:
toeplitz_solver <- function(a) {
# re-order a backwards, because we need to check diagonals from top-left
# to bottom right. if we don't reorder, we'll end up with top-right to
# bottom-left.
a <- a[, ncol(a):1]
# get all i and j (coordinates for every element)
i <- 1:nrow(a)
j <- 1:ncol(a)
# get all combinations of i and j
diags <- expand.grid(i, j)
# the coordinates for the diagonals are the ones where
# the sum is the same, e.g.: (3,2), (4,1), (2,3), (1,4)
sums <- apply(diags, 1, sum)
indexes <- lapply(unique(sums), function(x) {
diags[which(sums == x), ]
})
# indexes is now a list where every element is a list of coordinates
# the first element is a list for every coordinates for the first diag
# so on and so forth
results <- sapply(indexes, function(x) {
y <- a[as.matrix(x)]
return(all(y == y[1]))
})
# if every diagonal meets the condition, it is safe to assume that the
# input matrix is in fact toeplitz.
return(all(results))
}

R: how to find common elements with the same indices in multiple vectors

My question is somewhat similar to https://stackoverflow.com/questions/3695677/how-to-find-common-elements-from-multiple-vectors question. Suppose I have 3 vectors all of the same length:
v1 <- c(1, 99, 10, 11, 23)
v2 <- c(1, 99, 10, 23, 11)
v3 <- c(2, 4, 10, 13, 23)
Comparing v1 and v2:
It's easy to see that v1 and v2 have the same elements, which would be returned by Reduce(intersect, list(v1, v2)). However, I only want the overlap to be returned ONLY if their order in the vectors are the same as well. Therefore, I would only want to see 1 99 10 because they're both ordered as indices 1, 2, 3, respectively.
Comparing v1 and v3:
Here, 10 23 should be returned.
Comparing v2 and v3:
Only 10 should be returned.
In order to handle pairwise comparisons, I think I'll use a nested loop:
v_all = list(v1, v2, v3)
length_v = length(v_all) - 1
for(i in 1:length_v){
v_ind = 1:length(v_all)
v_2 = v_ind[-which(v_all == i)]
for(j in v_2){
#code for finding overlap
}
}
We can do this using a simple comparison check:
x == y
and subsetting x by it: x[x==y]. Then the question is how to best loop it over the combinations.
Here, I'll use outer to take the all by all output of each combination of the list of vectors, and call a Vectorized anonymous function on it.
v1 <- c(1, 99, 10, 11, 23)
v2 <- c(1, 99, 10, 23, 11)
v3 <- c(2, 4, 10, 13, 23)
l = list(v1,v2,v3)
outer(l,l,Vectorize(function(x,y){x[x==y]}))
[,1] [,2] [,3]
[1,] Numeric,5 Numeric,3 Numeric,2
[2,] Numeric,3 Numeric,5 10
[3,] Numeric,2 10 Numeric,5
if you look in the output matrix, each cell is the overlap of the indexed lists:
output[1,2]
[[1]]
[1] 1 99 10

Determining Whether a Matrix Has At Least One Zero Element

I'm sure this is trivial - nonetheless, any help would be appreciated.
The problem is simple: given a matrix, I'd like to get TRUE if the matrix in question has at least one element equal to zero. So, checking
A <- matrix(c(1, 2, 3, 4, 5, 0), nrow = 2, ncol = 3, byrow = TRUE)
> A
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 0
would return TRUE, while
B <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3, byrow = TRUE)
> B
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
would return FALSE.
Something like
if ( A == 0 ) { cat("\nZero detected")}
gives a warning. Is there a simple way to do this?
The warning is generated because you're presenting a vector of logical to if, which expects a single value. any is a function to tell if any of the logical values are TRUE:
any(A==0)
## [1] TRUE
any(B==0)
## [1] FALSE
There's also a function all which determines if all of the values in a logical vector are TRUE.
Try
0 %in% A
It should return TRUE or FALSE. It works for NA too:
x = matrix(1:24, ncol = 4)
x[3, 3] = NA
NA %in% x
#TRUE

Apply each row of a matrix for polyroot in R

I have amatrix m which includes different values of coefficients of a cubic polynomial, and I want to find the maximum real root of these cubic function. How can I do this in R?
m = matrix(c(1, 3, 4, 6, 7, 8, 9, 2, -3, -5, 6, 2), nrow = 3)
colnames(m) <- c("d", "c", "b", "a")
I would like to use polyroot for each row of the m matrix, How can I do this in R?
Wouldn't this just be:
apply(m , 1, polyroot)
... remembering, of course, that the results will be in column order.
apply( apply(m, 1,polyroot) , 2, function(x) ifelse( abs(Im(x)) < 0.00001, x,NA))
[,1] [,2] [,3]
[1,] NA -0.416256-0i -0.4167669+0i
[2,] NA NA NA
[3,] 2.34748+0i NA NA

Resources