Using dates as x axis in Makie.jl

Hello everyone,

I am trying to plot brackets in Makie.jl while using dates as the x axis. Unfortunately it gives me an error since I can’t use Date() as an argument in bracket!().

Here is the code that causes the error :

bracket!(ax2, Date(2020, 3, 17), 620, Date(2020, 5, 11), 620, text = "Confinement", style = :curly)

Here is my full code (the error is at the end) :

using CSV, DataFrames, CairoMakie, Dates, BenchmarkTools

# Parse the string into a date
function parse_date(date_string)
    v = parse.(Int, String.(split(date_string, "/")))
    return Date(v[3], v[2], v[1])
end
# Calcule décès par jours
function diff(v)
    diffs = zeros(Int, length(v))
    diffs[1] = v[1]
    for i in 2:length(v)
        diffs[i] = v[i] - v[i-1]
    end
    return diffs
end

data = DataFrame(CSV.File("COVID_Data_2.csv"), ["date", "nombre"])
data[!, :date] = parse_date.(data[!, :date])
data[!, :evo] = diff(data[!, :nombre])

begin

    f = Figure(size=(16*100, 9*100))

    # Évolution
    ax1 = Axis(f[1,1], 
        limits = (nothing, nothing, 0, 800),
        ylabel = "Nombre de décès par jours",
        ylabelfont = :bold
    )

    @views barplot!(ax1, data[!, :date], data[!, :evo])


    # Morts cumulés
    ax2 = Axis(f[1,1], aspect=(16/9), yaxisposition = :right,
        limits = (nothing, nothing, 0, 140_000),
        title = "Évolution des décès liés à la COVID du 18/03/2020 au 31/03/2023 en France métropolitaine",
        titlesize = 20,
        
        xlabel = "Date",
        ylabel = "Nombre cummulés de décès (en milliers)",
        xlabelfont = :bold,
        ylabelfont = :bold,
        yticks = ([i for i in 0:10_000:140_000], ["$i" for i in 0:10:140])
    )
    hidespines!(ax2)
    hidexdecorations!(ax2)
    @views lines!(ax2, data[!, :date], data[!, :nombre])


    # Confinement
    bracket!(ax2, Date(2020, 3, 17), 620, Date(2020, 5, 11), 620, text = "Confinement", style = :curly)
    f
end

Thank you for your help !

Since you can’t use Dates, substitute an Int index for the date and then customize ticks.

using CSV, DataFrames, CairoMakie, Dates, BenchmarkTools, Statistics

the_dates = collect(Date("2020-03-17"):Day(1):Date("2020-05-11"))# Parse the string into a date

λ = 0.12                    # decay rate (tune as needed)
raw = round.(Int, 2200 .* exp.(-λ .* (0:80)))
decay = unique(raw)         # drop repeated plateaus
decay[end] == 0 || push!(decay, 0) .* exp.(-λ .* (0:80))
the_deaths = unique(raw)         # drop repeated plateaus
the_deaths[end] == 0 || push!(the_deaths, 0)

data = DataFrame(date=the_dates, nombre=the_deaths)

data.evo = [nothing; diff(data[!, :nombre])]
data[1, 3] = 0
data[!, :evo] = Int.(coalesce.(data[!, :evo], 0))

f = Figure(size=(16 * 100, 9 * 100))
ax1 = Axis(f[1, 1])
ax2 = Axis(f[1, 2])


@views barplot!(ax1, data[!, :date], data[!, :evo])
# Pretend each date is 1, 2, … for the plot primitives
barplot!(ax2, xvals, data.evo)  # or whatever you’re plotting
tick_pos = round.(Int, range(1, length(data.date), length=7))
tick_pos = unique(tick_pos) # drop duplicates if the range collapsed

xvals = collect(eachindex(data.date))
tick_labels = Dates.format.(data.date[tick_pos], "yyyy-mm-dd")

ax2.xticks = (tick_pos, tick_labels)
ax2.xticklabelrotation[] = π / 4

bracket!(ax2,
    Point2f(first(xvals), 56),
    Point2f(last(xvals), 56);
    text="Confinement", style=:curly)

1 Like

Thank you very much ! It works perfectly !

1 Like

Just to add to this - if you want to retain the spacing of dates rather than just have them sequentially, you can use Dates functions to do so.

Date axis support in Makie was relatively recently added and has regressed on the last release, but I think the plan is that at some point in the future none of these hacks are necessary. For now, I’m doing the following:

const d2e = Dates.date2epochdays
maketicks(x; format = "d-u-yy") = (d2e.(x), Dates.format.(x, format))

lines(d2e.(my_data.date), my_data.value,
    axis = (; xlabel = "Date", ylabel = "Value", xticks = maketicks(Date(2020):Month(6):Date(2025, 7)), xticklabelrotation = π/4)
)

you can then use d2e.(some_dates) on (afaik) every plot type in Makie.

1 Like