Apply each row of a matrix for polyroot in R - 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

Related

Create a matrix with vector (not scalar) elements

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.

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))
}

Eigenvector Order in R

I am trying to work out an issue regarding the order of eigenvectors returned by eigen in r. Consider the following:
covmatrix <- matrix(data = c(13, 5, 2, 4), nrow = 2, ncol = 2)
covmatrix
eigen <- eigen(covmatrix)
eigen
The output returns:
values
[1] 14 3
vectors
[,1] [,2]
[1,] 0.8944272 -0.1961161
[2,] 0.4472136 0.9805807
Per the documentation, the first column should represent the eigenvector associated with the largest eigenvalue. However, mathematically, when I calculate the eigenvectors I end up with column 2 associated with the eigenvalue 14 as 0.9805807 is 5 times 0.1961161. The math is detailed here. I'm sure I am missing something simple but can't quite work it out.
You are not working with the same matrix. To get consistent result with what you derive analytically, you need
covmatrix <- matrix(data = c(13, 5, 2, 4), nrow = 2, ncol = 2, byrow = TRUE)
eigen(covmatrix)
$values
[1] 14 3
$vectors
[,1] [,2]
[1,] 0.9805807 -0.4472136
[2,] 0.1961161 0.8944272

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

Resources