How do I manipulate/access elements of an instance of "dist" class using core R?
There aren't standard ways of doing this, unfortunately. Here's are two functions that convert between the 1D index into the 2D matrix coordinates. They aren't pretty, but they work, and at least you can use the code to make something nicer if you need it. I'm posting it just because the equations aren't obvious.
distdex<-function(i,j,n) #given row, column, and n, return index
n*(i-1) - i*(i-1)/2 + j-i
rowcol<-function(ix,n) { #given index, return row and column
nr=ceiling(n-(1+sqrt(1+4*(n^2-n-2*ix)))/2)
nc=n-(2*n-nr+1)*nr/2+ix+nr
cbind(nr,nc)
}
A little test harness to show it works:
dist(rnorm(20))->testd
as.matrix(testd)[7,13] #row<col
distdex(7,13,20) # =105
testd[105] #same as above
testd[c(42,119)]
rowcol(c(42,119),20) # = (3,8) and (8,15)
as.matrix(testd)[3,8]
as.matrix(testd)[8,15]
as.matrix(d)
will turn the dist
object d
into a matrix, while as.dist(m)
will turn the matrix m
back into a dist
object. Note that the latter doesn't actually check that m
is a valid distance matrix; it just extracts the lower triangular part.
I don't have a straight answer to your question, but if you are using the Euclidian distance, have a look at the rdist
function from the fields
package. Its implementation (in Fortran) is faster than dist
, and the output is of class matrix
. At the very least, it shows that some developers have chosen to move away from this dist
class, maybe for the exact reason you are mentioning. If you are concerned that using a full matrix
for storing a symmetric matrix is an inefficient use of memory, you could convert it to a triangular matrix.
library("fields")
points <- matrix(runif(1000*100), nrow=1000, ncol=100)
system.time(dist1 <- dist(points))
# user system elapsed
# 7.277 0.000 7.338
system.time(dist2 <- rdist(points))
# user system elapsed
# 2.756 0.060 2.851
class(dist2)
# [1] "matrix"
dim(dist2)
# [1] 1000 1000
dist2[1:3, 1:3]
# [,1] [,2] [,3]
# [1,] 0.0000000001 3.9529674733 3.8051198575
# [2,] 3.9529674733 0.0000000001 3.6552146293
# [3,] 3.8051198575 3.6552146293 0.0000000001