Question

Consider a function that outputs a nested vector such as

[[[-0.6925523827697917 -0.4095089425269985]
  [-0.03856010899727634 0.8427233420960013]
  [-2.609986195686694E-13 -1.680032093051418E-12]]
 [[0.7203362514229046 -0.3494564274369062]]]

In between single brackets, i.e. [-0.6925523827697917 -0.4095089425269985], are numbers to be plotted in Cartesian coordinates.

Additionally there are vectors within another bracket, i.e.

[[0.7203362514229046 -0.3494564274369062]]

which denotes a cluster.

I am seeking to plot the points, which are the vectors above, and draw a line connecting points within a cluster. So, the points within the cluster [[-0.6925523827697917 -0.4095089425269985] [-0.03856010899727634 0.8427233420960013] [-2.609986195686694E-13 -1.680032093051418E-12]] would be connected.

My first thought would be to use Incanter's xy-plot. The part I am unsure is how to go from an indexed structure such as the vector to a point on the plot. Additionally, I am not sure how to draw a line connecting the clustered points. The example above should have one line (preferably smooth) through the three points in the first cluster, and no line through the last cluster since there is just one point within the cluster.

Was it helpful?

Solution

I'm not sure what you want, but as far as I got you, it's something like this:

(use '(incanter core charts interpolation))

(defn my-plot [[data [[cx cy]]]]
  (let [x       (map first data)
        y       (map second data)
        lbound  (apply min x)
        rbound  (apply max x)
        interp  (interpolate data :cubic-hermite)]
    (-> (function-plot interp lbound rbound)
        (add-points x y)
        (add-points [cx] [cy])
        view)))

cubic spline interpolation

I'm using :cubic-hermite spline interpolation to make the line smooth, and I'm using add-points function to add data points to the plot.

You'll find more interpolation examples here.

But three points isn't enough for good interpolation, so you should consider using linear interpolation instead:

(defn my-plot [[data [[cx cy]]]]
  (let [x (map first data)
        y (map second data)]
    (-> (xy-plot x y)
        (add-points x y)
        (add-points [cx] [cy])
        view)))

linear interpolation

Update:

Let's have a closer look at what I'm doing here.

First, I'm using destructuring to extract data points and cluster coordinates (I'm assuming that you always have a single cluster following your data points):

(defn my-plot [[data [[cx cy]]]]

Then I'm breaking nested vector of [x y] pairs into two vectors (one for each dimension):

  (let [x (map first data)
        y (map second data)]

Then I'm creating a plot object and drawing a line on it using your data points:

    (-> (xy-plot x y)

Then I'm adding original data point (blue dots):

        (add-points x y)

and your cluster (green dot):

        (add-points [cx] [cy])

Finally, I'm displaying resulting plot:

        view)))

In my first example I'm also using interpolation to make the line smoother:

        lbound  (apply min x)
        rbound  (apply max x)
        interp  (interpolate data :cubic-hermite)]
    (-> (function-plot interp lbound rbound)

I'm using function-plot here because interp object is a function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top