Julia: Heatmap with color gradient centered at 0

Viewed 537

In a heatmap, how could I create a three-color gradient, with blue for negative values, red for positive values and white for zero, such that with many zero values, much of the heatmap would be white (and not light red as with the default gradient).

A = [5 0 -3 -2 7; 0 5 0 0 0; -2 0 -1 0 0; -4 0 0 -10 0; 0 0 0 0 9]
using Plots
heatmap(Array(A),
    c = cgrad([:blue,:white,:red]),
    yflip = true,
    xlabel = "row", ylabel = "col",
    title = "Nonzeros, Positives, Negatives, in Matrix")

enter image description here

Here the gradient is automatically centered at the midpoint, a sensible default.

Related: here.

Post-Scriptum

As BallPointBen suggests, it would seem that computing the range of values is the recommended approach. Here is some benchmarking. The best approach, suggested by BallPointBen, is max = maximum(abs, A)

julia> using BenchmarkTools
julia> A = rand(10_000, 10_100)

julia> @btime max = maximum(abs.(A))
  432.837 ms (6 allocations: 770.57 MiB)
0.999999999929502

julia> @btime max = maximum(abs.(extrema(A)))
  339.597 ms (5 allocations: 144 bytes)
0.999999999929502

julia> @btime max = maximum(abs, A)
  60.690 ms (1 allocation: 16 bytes)
0.9999999985609005
1 Answers

You can compute the maximum absolute value in your array, then use it to set the clims argument. c.f. http://docs.juliaplots.org/latest/generated/attributes_subplot/

julia> max_val = maximum(abs, A)
10

julia> heatmap(Array(A),
           c = cgrad([:blue,:white,:red]),
           yflip = true,
           xlabel = "row", ylabel = "col",
           title = "Nonzeros, Positives, Negatives, in Matrix",
           clims=(-max_val, max_val))

enter image description here

Related