How to set custom x and y tick values in a Makie heatmap

2.9k views Asked by At

I want to make a heatmap in Julia using Makie (CairoMakie) with custom x and y tick values on the axes, like this one from Seaborn.

Any suggestions on how to modify the figure to het the months January to December on the Y-axis and the years 1949 to 1960 on the X-axis.

My code so far:

using DataFrames
using CSV
using CairoMakie

download("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/flights.csv", "flights.csv")
flights = DataFrame(CSV.File("flights.csv"))

data = Array(unstack(flights, :year, :month, :passengers)[!, 2:end])

fig = Figure()
ax = Axis(fig[1, 1], xlabel = "Year", ylabel = "Month")
hm = heatmap!(ax, data)

Colorbar(fig[1, 2], hm)

text!(ax,
    string.(data'),
    position = [Point2f(x, y) for x in 1:12 for y in 1:12],
    align = (:center, :center),
    color = ifelse.(data' .< 400, :white, :black),
    textsize = 14,
    )

save("figure.png", fig)

fig

enter image description here

2

There are 2 answers

0
René On BEST ANSWER

Just add xticks and yticks to Axis

ax = Axis(
    fig[1, 1], 
    xticks = (1:12, string.(1948 .+ (1:12))), 
    yticks = (1:12, Dates.monthname.(1:12)), 
    )

enter image description here

1
Anshul Singhvi On

If you just want to manually set the ticks, you can do:

using Dates
ax.yticks = 1:12
ax.ytickformat = x -> Dates.monthname.(Int.(x))

ax.xticks = 1:12
ax.xtickformat = x -> string.(x .+ 1948)

There is a somewhat better way to do this, though. You can specify data extents for your heatmap, by passing vectors or ranges for x and y before the data matrix.

You can do this by simply passing the desired x and y ranges, see below:

f = download("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/flights.csv")
flights = DataFrame(CSV.File(f))

data = unstack(flights, :year, :month, :passengers)

years = data.year

mat = Array(data[!, 2:end])

heatmap(years, 1:12, mat; axis = (yticks = 1:12, ytickformat = x -> Dates.monthname.(Int.(x)), xticks = years))
text!(
    string.(data'),
    position = [Point2f(x, y) for x in 1:12 for y in 1:12],
    align = (:center, :center),
    color = ifelse.(data' .< 400, :white, :black),
    textsize = 14,
    )

figure

and you can of course expand this, however suits your taste.