# Plots.jl: How can I get discrete colors in the colorbar of a heatmap?

**URL:** <https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660>\
**Category:** Visualization\
**Created:** [October 8, 2019, 4:29pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660 "2019-10-08T16:29:20Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![NiclasMattsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niclasmattsson/32/21988_2.png) [@NiclasMattsson](https://discourse.julialang.org/u/NiclasMattsson)\
**Post date:** [October 8, 2019, 4:29pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/1 "2019-10-08T16:29:20Z")

</div>

Simple example:

```julia
julia> r = rand(0:10,10,10)
10×10 Array{Int64,2}:
  0 4 10 1 10 1 6 3 6 3
  9 7 9 3 8 4 3 1 6 8
  8 7 6 2 8 7 8 8 2 9
  3 7 2 0 0 7 8 0 9 5
  2 6 0 3 4 9 1 10 6 2
  2 7 2 2 3 6 1 1 10 3
 10 9 4 2 0 3 10 6 0 9
  0 0 7 0 10 5 6 6 9 3
  6 3 1 10 4 10 6 7 0 4
  5 5 3 2 0 2 5 3 8 7

julia> heatmap(r)

```

![newplot(36)](https://global.discourse-cdn.com/julialang/original/3X/4/8/48966b2970bd3f115b3a5c5aabc5a7e1ccbdc516.png)

I want the colorbar to use the same 11 discrete colors as the heatmap. I also tried this but got the same result:

```julia
heatmap(r, c=[cgrad()[x] for x in 0:0.1:1])

```

Any ideas?

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [October 8, 2019, 6:43pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/2 "2019-10-08T18:43:56Z")

</div>

No, this is one of the most long-standing requests. [https://github.com/JuliaPlots/PlotUtils.jl/issues/3](https://github.com/JuliaPlots/PlotUtils.jl/issues/3)

---

<div class="post-metadata">

**Author:** ![NiclasMattsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niclasmattsson/32/21988_2.png) [@NiclasMattsson](https://discourse.julialang.org/u/NiclasMattsson)\
**Post date:** [October 8, 2019, 7:59pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/3 "2019-10-08T19:59:12Z")

</div>

Issue number 3, you’re not kidding. 🙂 Oh well, no problem. I just need one figure so I’ll do the legend manually. Thanks for the quick reply.

---

<div class="post-metadata">

**Author:** ![NiclasMattsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niclasmattsson/32/21988_2.png) [@NiclasMattsson](https://discourse.julialang.org/u/NiclasMattsson)\
**Post date:** [October 9, 2019, 10:31am UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/4 "2019-10-09T10:31:01Z")

</div>

Bump to ask the same question for other plotting packages such as Makie.jl or VegaLite.jl. After some quick tests I got the same continuous colorbar as above using these alternatives with no obvious options to change the behavior in the docs. Are discrete colormaps possible in other packages or does everything fall back on PlotUtils.jl (which doesn’t support this yet)?

---

<div class="post-metadata">

**Author:** ![jheinen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jheinen/32/2787_2.png) [@jheinen](https://discourse.julialang.org/u/jheinen)\
**Post date:** [October 9, 2019, 11:16am UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/5 "2019-10-09T11:16:33Z")

</div>

I added this feature to GR.jl. This could be transferred to `Plots/gr` in a similar way.

```julia
using GR
r = rand(0:10,10,10)
heatmap(r, levels=10)

```

 ![16](https://global.discourse-cdn.com/julialang/original/3X/c/6/c627aad1c87d0d38d784a03b6294204ee9612264.png)

---

<div class="post-metadata">

**Author:** ![jheinen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jheinen/32/2787_2.png) [@jheinen](https://discourse.julialang.org/u/jheinen)\
**Post date:** [October 9, 2019, 11:19am UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/6 "2019-10-09T11:19:03Z")

</div>

Right now, this does only affect the colorbar, **not** the heatmap.

---

<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:** [October 9, 2019, 1:35pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/7 "2019-10-09T13:35:45Z")

</div>

It can be done with GMT.jl

```julia
using GMT
r = rand(0:10,10,10);
C=makecpt(range=(0,10,1));
imshow(r, cmap=C, colorbar=true)

```

and one gets the fig bellow. Note that the fact that the border pixels are cut in half is not wrong. The issue is that there are 2 ways to referencing grids (this is a grid plot since data is not uint8). They are called `grid` and `pixel` registration in GMT vocabulary or `AREA_OR_POINT=Area` and `AREA_OR_POINT=Point` in GeoTiff. Some [more info at](https://docs.generic-mapping-tools.org/dev/cookbook/options.html#pixel-registration)

 ![GMTjl_tmp_grid](https://global.discourse-cdn.com/julialang/original/3X/f/d/fd9782e7323e8f448158ff77f73e1756087f07ee.png)

But we can get a non-clipped version with

```julia
G = mat2grid(r, 1); # Create a pixel registered grid
imshow(G, cmap=C, colorbar=true)

```

 ![GMTjl_tmp_pix](https://global.discourse-cdn.com/julialang/original/3X/3/4/341b0a26798814effc2d4560117572b72c862d6f.png)

---

<div class="post-metadata">

**Author:** ![NiclasMattsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niclasmattsson/32/21988_2.png) [@NiclasMattsson](https://discourse.julialang.org/u/NiclasMattsson)\
**Post date:** [October 9, 2019, 2:44pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/8 "2019-10-09T14:44:38Z")

</div>

Very nice, and thanks very much for the lightspeed development! Two small problems though: in this particular example there were 11 levels, not 10. When I run `heatmap(r, levels=11)`, the colorbar labels are slightly misaligned:

![qq2](https://global.discourse-cdn.com/julialang/original/3X/4/c/4c6698e3f71a70b2cd0b09d10f0a81b32b80920f.png)  
For discrete data the position of the label should probably be at the center of each color patch instead.

Second problem: when I ran `savefig()` to make this figure, the figure changed to a continuous colorbar and the x & y axes changed a bit too. Had to take a screenshot to post this.

Also, thanks for reminding me how incredibly fast vanilla GR is in terms of time to first plot!

---

<div class="post-metadata">

**Author:** ![NiclasMattsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niclasmattsson/32/21988_2.png) [@NiclasMattsson](https://discourse.julialang.org/u/NiclasMattsson)\
**Post date:** [October 9, 2019, 3:00pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/9 "2019-10-09T15:00:05Z")

</div>

Got this error when I tried to run the GMT example:

```julia
julia> imshow(G, cmap=C, colorbar=true)
ERROR: Expected a CPT structure for input
Stacktrace:
 [1] error(::String) at .\error.jl:33
 [2] palette_init(::Ptr{Nothing}, ::Bool, ::GMT.GMTgrid, ::UInt32) at C:\Users\niclas\.julia\packages\GMT\Ba3R6\src\gmt_main.jl:1166
 [3] GMTJL_Set_Object(::Ptr{Nothing}, ::GMT.GMT_RESOURCE, ::GMT.GMTgrid) at C:\Users\niclas\.julia\packages\GMT\Ba3R6\src\gmt_main.jl:795
 [4] gmt(::String, ::GMT.GMTgrid, ::Vararg{Any,N} where N) at C:\Users\niclas\.julia\packages\GMT\Ba3R6\src\gmt_main.jl:232
 [5] finish_PS_module(::Dict{Symbol,Any}, ::Array{String,1}, ::String, ::String, ::String, ::String, ::Bool, ::Bool, ::Bool, ::GMT.GMTgrid, ::Vararg{Any,N} where N) at C:\Users\niclas\.julia\packages\GMT\Ba3R6\src\common_options.jl:2186
 [6] #grdimage#95(::Bool, ::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:show, :cmap, :colorbar),Tuple{Bool,GMT.GMTcpt,Bool}}}, ::typeof(grdimage), ::String, ::GMT.GMTgrid, ::Nothing, ::Nothing) at C:\Users\niclas\.julia\packages\GMT\Ba3R6\src\grdimage.jl:88
 [7] #grdimage at .\none:0 [inlined] (repeats 2 times)
 [8] #imshow#125 at C:\Users\niclas\.julia\packages\GMT\Ba3R6\src\imshow.jl:59 [inlined]
 [9] (::getfield(GMT, Symbol("#kw##imshow")))(::NamedTuple{(:cmap, :colorbar),Tuple{GMT.GMTcpt,Bool}}, ::typeof(imshow), ::GMT.GMTgrid) at .\none:0
 [10] top-level scope at REPL[5]:1

```

The problem could be on my end since I just used my existing GMT installation which is maybe 6 months to a year old, but I don’t have any more time to reinstall or diagnose this problem today. Just thought I’d let you know.

---

<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:** [October 9, 2019, 3:47pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/10 "2019-10-09T15:47:40Z")

</div>

> [@joa-quim](#):
>
> C=makecpt(range=(0,10,1));

Since you are on Windows, updating GMT is completely painless (just use the installer in the GMT Github page). But you should not need to do it. It was my fault that didn’t repeat the `C=makecpt(range=(0,10,1));` step or the seconds case. That’s why it’s complaining about a missing CPT struct

```julia
using GMT
r = rand(0:10,10,10);
C=makecpt(range=(0,10,1));
G = mat2grid(r, 1); # Create a pixel registered grid
imshow(G, cmap=C, colorbar=true)

```

---

<div class="post-metadata">

**Author:** ![davidanthoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidanthoff/32/223493_2.png) [@davidanthoff](https://discourse.julialang.org/u/davidanthoff)\
**Post date:** [October 9, 2019, 4:17pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/11 "2019-10-09T16:17:38Z")

</div>

Here is the [VegaLite.jl](https://github.com/queryverse/VegaLite.jl) version of this:

```julia
using DataFrames, VegaLite

df = DataFrame(x=repeat(1:10, 10), y=repeat(1:10, inner=10), z=rand(0:10, 100));

df |> @vlplot(:rect, x="x:n", y="y:n", color="z:n")

```

And we get:  
 ![example2](https://global.discourse-cdn.com/julialang/original/3X/f/6/f6bcead38a677ed36ff80ef5f2e15781833204ec.png)

The trick here is to configure the scale for the color encoding as “nominal” via the `:n` shortcut.

Here is an alternative that looks maybe nicer? The weird thing is that this is not documented in the original vega-lite docs, and I just stumbled across this by accident, so not sure how “official” this actually is:

```julia
df |> @vlplot(:rect, x="x:n", y="y:n", color={"z:n", legend={type=:discrete}})

```

And we get:  
 ![example1](https://global.discourse-cdn.com/julialang/original/3X/3/d/3ddb6397e29189e859a20d090865ad26d7c1ab13.png)

---

<div class="post-metadata">

**Author:** ![jheinen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jheinen/32/2787_2.png) [@jheinen](https://discourse.julialang.org/u/jheinen)\
**Post date:** [October 9, 2019, 5:44pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/12 "2019-10-09T17:44:04Z")

</div>

The colorbar cells are now centered. For the `savefig()` problem, I don’t have an explanation right now … Will check it later this week …

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [October 9, 2019, 9:08pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/13 "2019-10-09T21:08:39Z")

</div>

The VegaLite example seems like it’s something else - a nominal color scale rather than an ordinal one as was requested, no?

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [October 9, 2019, 9:10pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/14 "2019-10-09T21:10:46Z")

</div>

It’d be very easy to add this in PlotUtils AFAICS. One way would be to add a `levels` field to `ColorGradient`, then use that to round the number value being passed to `getindex`. So you could do `heatmap(A, color = cgrad(:Spectral, levels = 9))`

---

<div class="post-metadata">

**Author:** ![davidanthoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidanthoff/32/223493_2.png) [@davidanthoff](https://discourse.julialang.org/u/davidanthoff)\
**Post date:** [October 9, 2019, 10:51pm UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/15 "2019-10-09T22:51:49Z")

</div>

> [@mkborregaard](#):
>
> The VegaLite example seems like it’s something else - a nominal color scale rather than an ordinal one as was requested

Ah, yes, you are right! Here is the version with an ordinal scale, and some other small adjustments (no legend title and color scheme that matches the original post):

```julia
df |> @vlplot(
  :rect,
  x="x:n",
  y="y:n",
  color={
    "z:o",
    scale={scheme="inferno"},
    legend={title=nothing, type=:discrete}
  }
)

```

We then get:  
 ![example4](https://global.discourse-cdn.com/julialang/original/3X/f/a/fab260662c96ed67f146b59a662d2ec2d2e3cd53.png)

So now I use the `:o` shortcut to declare the scale for the color as ordinal.

I’m also configuring the use of the `inferno` color scheme for the scale (you can see all the pre-defined schemes [here](https://vega.github.io/vega/docs/schemes/)). The options you have for configuring the scale are very broad in vega-lite, a full description is [here](https://vega.github.io/vega-lite/docs/scale.html).

And finally I’m removing the legend title, and then configure the type of the legend as `:discrete` (although I can’t find that option documented anywhere, it seems to work…).

---

<div class="post-metadata">

**Author:** ![pablosaa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosaa/32/20168_2.png) [@pablosaa](https://discourse.julialang.org/u/pablosaa)\
**Post date:** [January 21, 2021, 12:33am UTC](https://discourse.julialang.org/t/plots-jl-how-can-i-get-discrete-colors-in-the-colorbar-of-a-heatmap/29660/16 "2021-01-21T00:33:41Z")

</div>

With Plots.jl for me it works something like this:

```julia
using Plots
r = rand(0:10,10,10)
heatmap(r, color=palette(:hot, 11))

```

![hot_palette](https://global.discourse-cdn.com/julialang/original/3X/a/6/a615f6dfce7a3c4cad0c3faf80c0c569b22ff9ee.png)
