How do matrices handle dividing by 0? - r

I ran into an unexpected (to me) behavior with how R (R-3.0.3) handles Inf within a matrix.
scalar <- 1
mat1 <- matrix(0)
mat2 <- matrix(1)
mat2 <- -log(mat2)
# > mat1
# [,1]
# [1,] 0
#
# > mat2
# [,1]
# [1,] 0
(mat1[1,1] - scalar[1])/mat1[1,1]
# [1] -Inf
(mat2[1,1] - scalar[1])/mat2[1,1]
# [1] Inf
Why don't both give -Inf? I do not see anything the help file for matrix. I also could not tell a difference between mat1 and mat2 using class, str or dput.

I'll just summarize the discussion on the comments to close out the question.
First, this behavior is not specific to matrices, observe
a<- 0; (a-1)/a
# [1] -Inf
a<- -log(1); (a-1)/a
# [1] Inf
but rather is it a result of the intricacies of IEEE floating point arithmetic. Despite the fact that
-log(1) == 0
# [1] TRUE
zero can actually hold a sign. There is a "+0" and a "-0" and -log(1) returns the latter. Adding +0 to a negative zero value should make it a "regular" zero.
a<- -log(1)+0; (a-1)/a
# [1] -Inf

Related

Multiply a matrix' columns by its columns

I have a 4x100 matrix where I would like to multiply column 1 with row 1 in its transpose etc and store these matrices somewhere to be able to take the sum of these new matrices lateron.
I really don't know where to start due to the fact that I get 4x4 matrices after the column-row-multiplication. Due to this fact I cannot store them in a matrix
data:
mm num[1:4,1:100]
mm_t num[1:100,1:4]
I'm thinking of creating a list in some way
list1=list()
for(i in 1:100){
list1[i] <- mm[,i]%*%mm_t[i,]
}
but I need some more indices i think because this just leaves me with a number in each argument..
First, your call for data is not clear. Second, are you tryign to multiply each value by itself, or do matrix multiplication
We create a 4x100 matrix and its transpose:
mm <- matrix(1:400, nrow = 4, ncol = 100)
mm.t <- t(mm)
Then we can do the matrix multiplication (which is what you did, and you get a 4 x 4 matrix from the definition of matrix multiplication https://www.wikiwand.com/en/Matrix_multiplication)
If we want to multiply each index by itself (so mm[1,1] by mm [1,1]) then:
mm * mm
This will result in 4x100 matrix where each value is the square of the original value.
If we want the matrix multiplication of each column with itself, then:
sapply(1:100, function(x) {
mm[, x] %*% mm[, x]
})
This results in 100 values: each one is the matrix product of a 4x1 vector with itself.
Let's start with some sample data. Please get in the habit of including things like this in your question:
nr = 4
nc = 100
set.seed(47)
mm = matrix(runif(nr * nc), nrow = nr)
Here's a working answer, very similar to your attempt:
result = list()
for (i in 1:ncol(mm)) result[[i]] = mm[, i] %*% t(mm[, i])
result[1:2]
# [[1]]
# [,1] [,2] [,3] [,4]
# [1,] 0.9544547 0.3653018 0.7439585 0.8035430
# [2,] 0.3653018 0.1398132 0.2847378 0.3075428
# [3,] 0.7439585 0.2847378 0.5798853 0.6263290
# [4,] 0.8035430 0.3075428 0.6263290 0.6764924
#
# [[2]]
# [,1] [,2] [,3] [,4]
# [1,] 0.3289532 0.3965557 0.2231443 0.2689613
# [2,] 0.3965557 0.4780511 0.2690022 0.3242351
# [3,] 0.2231443 0.2690022 0.1513691 0.1824490
# [4,] 0.2689613 0.3242351 0.1824490 0.2199103
As to why yours didn't work, we can experiment and see that indeed we get a number rather than a matrix. The reason is that when you subset a single row or column of a matrix, the dimensions are "dropped" and it is coerced to a plain vector. And when you matrix multiply two vectors, you get their dot product.
mmt = t(mm)
mm[, 1] %*% mmt[1, ]
# [,1]
# [1,] 2.350646
dim(mm[, 1])
# NULL
dim(mmt[1, ])
# NULL
We can avoid this by specifying drop = FALSE in the subset code
dim(mmt[1, , drop = FALSE])
# [1] 1 4
And thus slightly modify your attempt, just adding drop = FALSE will make it work.
res2 = list()
for (i in 1:ncol(mm)) res2[[i]] = mm[, i] %*% mmt[i, , drop = FALSE]
identical(result, res2)
# [1] TRUE

Why am I not getting the index value of a matrix using the which function?

I have a matrix of thousands of coordinate values. And all I want is to find the index of a chosen value. I use this:
which(long == -118.1123, arr.ind=TRUE)
But I don't get any value. All I get is blank row and column. However, when I do this, I get values.
which(long < -118.1123, arr.ind=TRUE)
I know this value exists because I have manually checked in the Rstudio pane as well as printed out the value using long[1,2] etc.
dput(long) doesn't work with matrices. Hope you can help.
Diagnosis as per comments
- long[1,1]
[1] -118.0981
- long[1,1]==-118.0981
[1] FALSE
Here's an example of using a test that allows a "fuzz-factor" difference to be ignored:
> M <- matrix(rnorm(10) , 5,2)
> M
[,1] [,2]
[1,] -0.2382021 2.1698010
[2,] -1.1617644 -1.1513516
[3,] 1.3597808 0.9365208
[4,] 0.7460694 -1.7216410
[5,] -0.2413117 -0.1780468
> which(M==-0.2382021, arr.ind=TRUE)
row col
> which(abs(M - -0.2382021) < 0.0000001, arr.ind=TRUE)
row col
[1,] 1 1
My comment suggesting all.equal didn't work with a matrix argument inside which. I checked with #RHertel's choice of signif and it does succeed.
> which(signif(M,7) == -0.2382021, arr.ind=TRUE)
row col
[1,] 1 1
Your numerical value in the matrix may not be exactly equal to -118.1123. It may contain several digits that aren't displayed since the machine's accuracy is much higher and a perfect identity may not be obtained due to minimal roundoff errors.
I suggest that you try
which(signif(long,7) == -118.1123, arr.ind=TRUE)
Here's a simple example illustrating the problem:
Let's first fill a vector with random numbers between 0 and 1:
v <- runif(100)
Then we redefine an arbitrary element of the vector, say element 42, and set it equal to pi:
v[42] <- pi
> v[42]
#[1] 3.141593
However, if we test for equality using "==" the result is FALSE:
> v[42] == 3.141593
#[1] FALSE
But if we only consider the first seven significant digits, the position 42 can be extracted from the vector:
> which(signif(v,7) == 3.141593, arr.ind = T)
#[1] 42
Now, to address your comment, let's assume that you're trying to find the number that is closest to 3.141591 among all your elements in the vector v. We can be certain that this will be element 42, but R should find out. This result can be obtained with
> order(abs(v-3.141591))[1]
#[1] 42

R Matrix Multiplication Error with Proper Dimensions

I am trying to multiply matrices in R. However, I am unable to do so without error. The multiplication of the dimensions seem right, but not sure what it could be. Here is some background on my data and what my loop is. Thanks for the help.
t
# [1] 6848
dim(A)
# [1] 2 2
dim(backward)
# [1] 6848 2
dim(B)
# [1] 6848 2
is.matrix(A)
# [1] TRUE
is.matrix(backward)
# [1] TRUE
is.matrix(B)
# [1] TRUE
for (i in (t-1):1){ #FIXXXXX
backward[i,] = t(A%*%(t(backward[i+1,])))*B[i+1,]
}
Error in A %*% (t(backward[i + 1, ])) : non-conformable arguments
By default, selecting a single row or column from a matrix results in a vector. Add drop=FALSE to your subsetting expression to keep this from happening.
t(A %*% t(backward[i+1, , drop=FALSE])) * B[i+1, , drop=FALSE]
And by the way, it would probably be a good idea to rename your t variable to something else, as t is also the transpose function.

R error on matrix multiplication: non-conformable arguments

I have an R loop that has been giving me error. Here are the dimensions of the matrices..
> dim(A)
[1] 2 2
> dim(backward)
[1] 6848 2
I am trying to run this loop and get the following error:
for (i in t:1){
backward[i,]=A%*%t(backward[i,])}
Error in A %*% t(backward[i, ]) : non-conformable arguments
Where t equals 6848. Thanks for your time.
EDIT with bgoldst code:
> A
[,1] [,2]
[1,] 0.8 0.2
[2,] 0.2 0.8
> backward <- matrix(1:(t*2),t,2);
> dim(backward)
[1] 6848 2
> for (i in t:1) backward[i,] <- A%*%t(backward[i,,drop=F]);
Error in A %*% t(backward[i, , drop = F]) : non-conformable arguments
I'm guessing that your expectation of
backward[i,]
is that it will return a 1x2 matrix, which you would be able to use as the operand of a matrix multiplication. This is incorrect. In R, when you specify a single index within a dimension of a matrix, then by default, R will "drop" that dimension. In the case of the above piece of code, the row dimension is dropped, and you end up with a vector, whose contents are taken from all columns along the indexed row. A vector is not a valid operand to a matrix multiplication.
You can solve this problem by providing the drop argument to the [ operation:
A <- matrix(1:(2*2),2,2);
backward <- matrix(1:(6848*2),6848,2);
t <- nrow(backward); for (i in t:1) backward[i,] <- A%*%t(backward[i,,drop=F]); ## no error
Here's a demo of the effect of drop=F:
backward[1,]
## [1] 20548 27398
backward[1,,drop=F]
## [,1] [,2]
## [1,] 20548 27398
See ?`[` for more info.
Here's a solution that doesn't depend on the drop=F argument:
for (i in t:1) backward[i,] <- A%*%t(matrix(backward[i,],1));

R - min, max and mean of off-diagonal elements in a matrix

I have like a matrix in R and I want to get:
Max off - diagonal elements
Min off – diagonal elements
Mean off –diagonal elements
With diagonal I used max(diag(A)) , min(diag(A)) , mean(diag(A)) and worked just fine
But for off-diagonal I tried
dataD <- subset(A, V1!=V2)
Error in subset.matrix(A, V1 != V2) : object 'V1' not found
to use:
colMeans(dataD) # get the mean for columns
but I cannot get dataD b/c it says object 'V1' not found
Thanks!
Here the row() and col() helper functions are useful. Using #James A, we can get the upper off-diagonal using this little trick:
> A[row(A) == (col(A) - 1)]
[1] 5 10 15
and the lower off diagonal via this:
> A[row(A) == (col(A) + 1)]
[1] 2 7 12
These can be generalised to give whatever diagonals you want:
> A[row(A) == (col(A) - 2)]
[1] 9 14
and don't require any subsetting.
Then it is a simple matter of calling whatever function you want on these values. E.g.:
> mean(A[row(A) == (col(A) - 1)])
[1] 10
If as per my comment you mean everything but the diagonal, then use
> diag(A) <- NA
> mean(A, na.rm = TRUE)
[1] 8.5
> max(A, na.rm = TRUE)
[1] 15
> # etc. using sum(A, na.rm = TRUE), min(A, na.rm = TRUE), etc..
So this doesn't get lost, Ben Bolker suggests (in the comments) that the above code block can be done more neatly using the row() and col() functions I mentioned above:
mean(A[row(A)!=col(A)])
min(A[row(A)!=col(A)])
max(A[row(A)!=col(A)])
sum(A[row(A)!=col(A)])
which is a nicer solution all round.
In one simple line of code:
For a matrix A if you wish to find the Minimum, 1st Quartile, Median, Mean, 3rd Quartile and Maximum of the upper and lower off diagonals:
summary(c(A[upper.tri(A)],A[lower.tri(A)])).
The diag of a suitably subsetted matrix will give you the off-diagonals. For example:
A <- matrix(1:16,4)
#upper off-diagonal
diag(A[-4,-1])
[1] 5 10 15
#lower off-diagonal
diag(A[-1,-4])
[1] 2 7 12
To get a vector holding the max of the off-diagonal elements of each col or row of a matrix requires a few more steps. I was directed here when searching for help on that. Perhaps others will do the same, so I offer this solution, which I found using what I learned here.
The trick is to create a matrix of only the off-diagonal elements. Consider:
> A <- matrix(c(10,2,3, 4,10,6, 7,8,10), ncol=3)
> A
[,1] [,2] [,3]
[1,] 10 4 7
[2,] 2 10 8
[3,] 3 6 10
> apply(A, 2, max)
[1] 10 10 10
Subsetting using the suggested indexing, A[row(A)!=col(A)] produces a vector of off-diagonal elements, in column-order:
> v <- A[row(A)!=col(A)]
> v
[1] 2 3 4 6 7 8
Returning this to a matrix allows the use of apply() to apply a function of choice to a margin of only off-diagonal elements. Using the max function as an example:
> A.off <- matrix(v, ncol=3)
> A.off
[,1] [,2] [,3]
[1,] 2 4 7
[2,] 3 6 8
> v <- apply(A.off, 2, max)
> v
[1] 3 6 8
The whole operation can be compactly—and rather cryptically—coded in one line:
> v <- apply(matrix(A[row(A)!=col(A)], ncol=ncol(A)), 2, max)
> v
[1] 3 6 8
Just multiply matrix A by 1-diag (nofelements)
for example if A is a 4x4 matrix, then
mean(A*(1-diag(4)) or A*(1-diag(nrow(A)))
This is faster when you need to run the same line of code multiple times
In addition to James' answer, I want to add that you can use the diag function to directly exclude all diagonal elements of a matrix by use of A[-diag(A)]. For example, consider:
summary(A[-diag(A)])

Resources