Pairwise distances from a single column or vector

I’m a new Julia user, so this might be really obvious, but is there a straight-forward way to generate a pairwise distance matrix from a single vector or column?
In R, it’s pretty straightforward:
for the vector c(2, 4, 6, 8)

dist(c(2, 4, 6, 8))
1 2 3
2 2
3 4 2
4 6 4 2

I’ve played around with Distances.jl, but I’m having trouble getting the function pairwise to work even for simple instances, e.g.:

using Distances
cc = [2, 4, 6, 8];
mm = [1, 3, 5, 7];
pairwise(Euclidean(), cc)

ERROR: MethodError: no method matching pairwise(::Euclidean, ::Array{Int64,1})

pairwise(Euclidean(), cc, mm)

ERROR: MethodError: no method matching pairwise(::Euclidean, ::Array{Int64,1}, ::Array{Int64,1})

The non-pairwise version works. This obviously isn’t what I’m going for, but at least it demonstrates that some of the functionality of Distances.jl is up and running:
euclidean(cc, mm)
2.0

I don’t know enough R to know exactly what you’re expecting, but shouldn’t the distance matrix be a 4x4 matrix? If that’s what you want, then it’s easy to write a simple Julia function to do this for you using a list comprehension:

julia> using LinearAlgebra: norm

julia> c = [2, 4, 6, 8]
4-element Array{Int64,1}:
 2
 4
 6
 8
                                                                                                                                                                                                                                                                                                                                      
julia> [norm(c[i] - c[j]) for i in eachindex(c), j in eachindex(c)]
4×4 Array{Int64,2}:                                                                                                                                                                                                                                                                                                                   
 0  2  4  6                                                                                                                                                                                                                                                                                                                           
 2  0  2  4
 4  2  0  2
 6  4  2  0
2 Likes

In Distances, a collection of points (even if the points are one dimensional) is given as a matrix, not a vector. So either create it as a matrix or use the adjoint operator ' to give it an extra dimension.

julia> pairwise(Euclidean(), cc'; dims=2)
4×4 Array{Float64,2}:
 0.0  2.0  4.0  6.0
 2.0  0.0  2.0  4.0
 4.0  2.0  0.0  2.0
 6.0  4.0  2.0  0.0
1 Like

Thanks very much! I’m hoping to apply this method to large numbers of large numbers, so the implementation suggested by kristoffer.carlsson below might be faster

re: output: the output in R is in the “lower triangle” format with no zeros, so it’s just:
2
4 2
6 4 2

that’s eventually the format I’ll need things in, but I can play around with converting the output of your function. I’m pretty sure there are quick and dirty tricks to convert among distance matrix types

Thanks very much for this response! Just to tack on for any future newbies who stumble upon this, if you want to generate a pairwise distance matrix from just one column of a 2d matrix, you can do:

julia> ccc = [2 4 6 ; 4 8 16 ; 6 12 18; 8 16 64]; 
julia> pairwise(Euclidean(), ccc[ : , 1]'; dims = 2)
4×4 Array{Float64,2}:
 0.0  2.0  4.0  6.0
 2.0  0.0  2.0  4.0
 4.0  2.0  0.0  2.0
 6.0  4.0  2.0  0.0
1 Like

You can still use Robin’s answer, which I actually prefer, in a more simplified way:

julia> c = [2.0, 4, 6, 8]
4-element Array{Float64,1}:
 2.0
 4.0
 6.0
 8.0

julia> [abs(i-j) for i in c, j in c]
4×4 Array{Float64,2}:
 0.0  2.0  4.0  6.0
 2.0  0.0  2.0  4.0
 4.0  2.0  0.0  2.0
 6.0  4.0  2.0  0.0
2 Likes

There is also Distances.jl.

1 Like

Yes, I know, it’s a matter of preference, I don’t like to use a package unless I’m doing serious work with it.

2 Likes