1

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.

Leonid Beschastny
  • 50,364
  • 10
  • 118
  • 122
sunspots
  • 1,047
  • 13
  • 29

1 Answers1

1

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.

Leonid Beschastny
  • 50,364
  • 10
  • 118
  • 122
  • If I wanted to plot without the interpolation what would be required to remove from the first function? I tried removing the line `interp` and interp from `function-plot` but am passing too many args to the function (2). – sunspots Mar 25 '14 at 19:12
  • See my second example for plot without interpolation. – Leonid Beschastny Mar 25 '14 at 21:22
  • Using the latter my-plot, how would I modify it to plot the original points and the clusters in the same graph? @LeonidBeschastny – sunspots Mar 26 '14 at 19:00
  • Also, I haven't been able to figure out the green dot that appears in all of the graphs. Could you please explain this object. – sunspots Mar 26 '14 at 19:24
  • Green dot IS your cluster. =) – Leonid Beschastny Mar 26 '14 at 19:41
  • Ok, now I see. But I meant to plot all vectors output, i.e. floating points with a single bracket [...]. Then to plot on the same graph all clusters, i.e. vectors within a bracket []. So clusters are the entities with double brackets [[...]] @LeonidBeschanstny – sunspots Mar 26 '14 at 20:00
  • The following function would find the center of the cluster `(defn arithmeans [& x] (map #(/ % (count x)) (apply map + x)))` – sunspots Mar 26 '14 at 20:02
  • My goal was to demonstrate the principles of plotting in Incanter, so I assumed that you always have a single cluster following all your data points. – Leonid Beschastny Mar 26 '14 at 20:06