# How to find the elbow of a graph in Julia

**URL:** <https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912>\
**Category:** General Usage\
**Created:** [April 2, 2020, 4:49pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912 "2020-04-02T16:49:23Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Julia1](https://avatars.discourse-cdn.com/v4/letter/j/db5fbb/32.png) [@Julia1](https://discourse.julialang.org/u/Julia1)\
**Post date:** [April 2, 2020, 4:49pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/1 "2020-04-02T16:49:23Z")

</div>

Hi how’s it going?

A common technique to finding the optimal number for K in K-means clustering is to use the elbow method. You try different values of K, and plot the average euclidean distance from the points to their cluster centers, and find the location on the graph that resembles an “elbow”.

In Python there are some quick packages to implement this, and in Julia I’ve reached a point (no pun intended) where I have the elbow graphs all implemented. Here is an image of one.

How would you recommend I extract the X axis value from the elbow of this graph (in this case X=2) as the optimal number for K.

![Screenshot from 2020-04-02 12-48-41](https://global.discourse-cdn.com/julialang/original/3X/d/9/d9f8bbec18acca15a7e5fbbf46beb9431d686514.png)

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [April 2, 2020, 7:17pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/2 "2020-04-02T19:17:05Z")

</div>

Compute the distance to a line made up with with first and last point of your broken line. The elbow point it’s the furthest one.  
Example with [GMT.jl](https://github.com/GenericMappingTools/GMT.jl)

```julia
using GMT
xy = [1.0 9.0; 2.9 6.1; 4.6 3.5; 7.0 2.3; 9.1 1.3]; # Example poly-line

mapproject(xy, dist2line=(line=[xy[1:1, :]; xy[end:end, :]], unit=:cartesian))
Array{GMT.GMTdataset,1} with 1 segments
First segment DATA
5×5 Array{Float64,2}:
 1.0 9.0 0.0 1.0 9.0
 2.9 6.1 0.79278 3.44621 6.67459
 4.6 3.5 1.50592 5.63756 4.59146
 7.0 2.3 0.722092 7.49751 2.82335
 9.1 1.3 0.0 9.1 1.3

```

third column holds the distance to line. The elbow is the third point.

Sorry for the not intuitive `unit=:cartesian` keyword. It will become `cartesian=true` in next version.

---

<div class="post-metadata">

**Author:** ![Julia1](https://avatars.discourse-cdn.com/v4/letter/j/db5fbb/32.png) [@Julia1](https://discourse.julialang.org/u/Julia1)\
**Post date:** [April 3, 2020, 12:22pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/3 "2020-04-03T12:22:39Z")

</div>

Thank you! Do you know of any other packages / functions within plots to do these calculations? I’m having a difficult time getting GMT up and running. I totally get the formula though makes a lot of sense, just want to know if there are any simpler implementations

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [April 3, 2020, 1:03pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/4 "2020-04-03T13:03:27Z")

</div>

You could look at [GitHub - mfalt/EllZeroTrendFiltering.jl: ℓ0 Trend Filtering - Continuous, Piecewise Linear Approximations with few segments.](https://github.com/mfalt/EllZeroTrendFiltering.jl) although it looks like it might be a bit more than you need.

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [April 3, 2020, 1:06pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/5 "2020-04-03T13:06:37Z")

</div>

Does anyone have good references for standard algorithms for this problem? It comes up a lot also when using PCA/SVD to identify a subspace in noisy data. I haven’t needed to automatically determine the dimensionality from the data (I often know it _a priori_) but it would be nice to have a good place to start looking.

---

<div class="post-metadata">

**Author:** ![Gyoshi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gyoshi/32/7119_2.png) [@Gyoshi](https://discourse.julialang.org/u/Gyoshi)\
**Post date:** [April 3, 2020, 1:21pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/6 "2020-04-03T13:21:50Z")

</div>

Finding the point furthest from the line made with the first and last point misses the purpose of the elbow method. I would warn against using this for cases other than when you are just trying to the elbow point of two straight lines.

As per my limited understanding, the elbow method is about identifying the last number which leads to a significant (per subjective judgement) reduction in the sum of squared distances to the mean points. As you can see [here](https://predictivehacks.com/k-means-elbow-method-code-for-python/), the author identifies 3 as the elbow point—not 2 which is at a sharper bend and furthest away from the above-mentioned line.

@Julia1 I am curious which Python packages you have used for this, and how their decision algorithms judge which point is the elbow.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [April 3, 2020, 1:52pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/7 "2020-04-03T13:52:35Z")

</div>

> [@Gyoshi](#):
>
> the author identifies 3 as the elbow point—not 2 which is at a sharper bend and furthest away from the above-mentioned line.

If you had plotted my example data you would have seen that the 3rd point is obviously the furthest point. But, note that my response was only based on geometric question posted by the OP. And for that it works pretty well

```julia
xy = [1.0 9.0; 2.9 6.1; 4.6 3.5; 7.0 2.3; 9.1 1.3];
plot(xy, savefig="elbow.png", lw=0.5, marker=:circle, ms=0.2, mc=:red, show=1)

```

 ![elbow](https://global.discourse-cdn.com/julialang/original/3X/9/6/96e49f7cb5d2a6d074eb5ce014939b0bea320008.png)

---

<div class="post-metadata">

**Author:** ![Gyoshi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gyoshi/32/7119_2.png) [@Gyoshi](https://discourse.julialang.org/u/Gyoshi)\
**Post date:** [April 3, 2020, 2:01pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/8 "2020-04-03T14:01:47Z")

</div>

Apologies for the confusion, by ‘the author’ I was referring to the author of the article which I linked to.

Indeed the code may work well for the present geometric question, I only wanted to caution against using this solution in determining the elbow point in the general case.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [April 3, 2020, 2:12pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/9 "2020-04-03T14:12:34Z")

</div>

> [@Julia1](#):
>
> I’m having a difficult time getting GMT up and running.

Can you please open an issue in [GMT.jl](https://github.com/GenericMappingTools/GMT.jl). I know that on unix when GMT was not installed in standard location the OS fails to find the shared libs.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [April 3, 2020, 2:17pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/10 "2020-04-03T14:17:46Z")

</div>

Ok, I see your point and you are right. Perhaps compute the slopes and find the max variation? Or some smooth variation of it if there are outliers.

---

<div class="post-metadata">

**Author:** ![Julia1](https://avatars.discourse-cdn.com/v4/letter/j/db5fbb/32.png) [@Julia1](https://discourse.julialang.org/u/Julia1)\
**Post date:** [April 3, 2020, 2:27pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/11 "2020-04-03T14:27:57Z")

</div>

I used the Yellowbrick Package. Here is the code. [Elbow Method — Yellowbrick v1.5 documentation](https://www.scikit-yb.org/en/latest/api/cluster/elbow.html)

---

<div class="post-metadata">

**Author:** ![Julia1](https://avatars.discourse-cdn.com/v4/letter/j/db5fbb/32.png) [@Julia1](https://discourse.julialang.org/u/Julia1)\
**Post date:** [April 3, 2020, 2:28pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/12 "2020-04-03T14:28:56Z")

</div>

Yes I’ll do that. That’s the exact error I’m getting.

---

<div class="post-metadata">

**Author:** ![Gyoshi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gyoshi/32/7119_2.png) [@Gyoshi](https://discourse.julialang.org/u/Gyoshi)\
**Post date:** [April 3, 2020, 2:51pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/13 "2020-04-03T14:51:08Z")

</div>

Thanks for the link; What you can also try is use the same “knee point detection” algorithm that Yellowbrick is using ([GitHub - arvkevi/kneed: Knee point detection in Python](https://github.com/arvkevi/kneed)) and import it to Julia via [PyCall.jl](https://github.com/JuliaPy/PyCall.jl)

---

<div class="post-metadata">

**Author:** ![70Gage70](https://avatars.discourse-cdn.com/v4/letter/7/e68b1a/32.png) [@70Gage70](https://discourse.julialang.org/u/70Gage70)\
**Post date:** [September 27, 2024, 5:57pm UTC](https://discourse.julialang.org/t/how-to-find-the-elbow-of-a-graph-in-julia/36912/14 "2024-09-27T17:57:40Z")

</div>

For future internet travelers: there is now [Kneedle.jl](https://github.com/70Gage70/Kneedle.jl).

```julia
using Kneedle, CairoMakie

x = [1.0, 2.9, 4.6, 7.0, 9.1]
y = [9.0, 6.1, 3.5, 2.3, 1.3]
kr = kneedle(x, y)
viz(x, y, kr, show_data_smoothed = false)

```

 ![kneedle-test](https://global.discourse-cdn.com/julialang/original/3X/7/6/7684aee6cca3e8c9cc89176d3d2a9b48048aa7d1.png)
