I’ve come across this problem many times, but I can’t find any mentions of it anywhere on here or the Plots repo. Consider:
julia> using Plots
julia> histogram(rand(Date(2000, 1, 1):Day(1):Date(2001, 1, 1), 100))
Here, Plots uses Dates.value(date)
on the x-axis, which means one has to be pretty good at mental arithmetic to interpret what the graph actually shows. I’ve tried using xformatter = x -> string(Date(0) + Day(x))
but to no avail (yes, I’ve also forgotten which function gives a Date
from the Dates.value
of a date, something I asked Jacob a long time ago on Slack…)
Are there issues related to this that I’ve missed? And does anybody have an idea for a workaround?
Relatedly, I just realized that histogram
entirely ignores xformatter
and yformatter
kwargs:
julia> histogram(rand(1_000:2_000, 100), yformatter = x -> x/1_000)
but
julia> plot(rand(1_000:2_000, 100), yformatter = x -> x/1_000)
This seems to work (no bells and whistles):
using Dates, Plots; gr()
d1, d2 = Date(2000, 1, 1), Date(2001, 1, 1)
d = rand(d1:Day(1):d2, 100)
de = Dates.date2epochdays.(d)
xb = range(Dates.date2epochdays(d1), stop = Dates.date2epochdays(d2), length=5)
xd = Dates.epochdays2date.(round.(Int,xb))
histogram(de, bins = xb, xticks=false, label="Dates histogram")
plot!(xticks=(xb,xd), ylims=(0,40))
1 Like
Thanks, although it is of course severly limiting if one has to specify bins manually…
If one knows the exact algorithm used by histogram()
, one could set the manual value in workaround above equal to the automatic value.
This could be obtained from a command like:
nbins = length(fit(Histogram,de).edges[1]) - 1
Actually I’ve found an easier workaround: while histogram
ignores formatters, they can be added to an existing histogram if it is plotted again. So:
plot(histogram(rand(Date(2000, 1, 1):Day(1):Date(2001, 1, 1), 100)),
xformatter = x -> Dates.epochdays2date(x+365))
(Thanks for reminding me of the epochdays2date function!)
2 Likes
@nilshg, could you please verify the plot posted as the dates displayed run back to 1998 while the input data are from 2000 onward.
Indeed - it looks as though Dates.value
is offset by one year from the epochdays2date
julia> Dates.value(Date(2000, 1, 1))
730120
julia> Dates.epochdays2date(730120)
1999-01-01
so above one needs Dates.epochdays2date(x+365)
to get the right answer
1 Like
I’m pretty sure I ran into this offset by 1 year issue quite a while ago. I ended up defining a conversion function that adjusted by the 1 year at the time.
That code has long since gone by the wayside.