# How to create a histogram of annual events, such as cherry blossom time

I have calculated blooming and ripening times for a specific variety of plant, based on actual temperature data from over 40 years. I would like to create two histograms on a single axis; one for blossoming and one for ripening. Surely there is a more straightforward way than converting to integer dates and adjusting for leap years…

Here is some actual data (years have been removed) in the form of {month, day}:

{
{4, 3}, {4, 22}, {4, 15}, {4, 2}, {4, 18},
{4, 20}, {4, 12}, {3, 30}, {4, 4}, {4, 24},
{4, 26}, {3, 4}, {4, 26}, {4, 13}, {5, 1},
{4, 4}, {4, 8}, {4, 18}, {4, 9}, {4, 19},
{4, 10}, {4, 20}, {4, 3}, {4,4}, {3, 21},
{4, 19}, {4, 15}, {4, 17}, {4, 9}, {4, 17},
{4, 9}, {4, 8}, {4, 23}, {4, 17}, {4, 1},
{4, 10}, {4, 15}, {4, 15}, {4, 11}, {4, 15},
{4, 19}, {4, 22}, {4, 11}, {4, 4}, {4, 12},
{3, 27}, {3, 24}, {4, 26}, {3, 28}, {4, 16}
}

-
Please include an example of the output you desire. – Mr.Wizard Feb 26 '12 at 1:49
For example, there is a question right below yours that includes how to create this: i.stack.imgur.com/r9uMh.png – Mr.Wizard Feb 26 '12 at 1:51
Are those values {month, day}? – Brett Champion Feb 26 '12 at 2:41
Wow. Thanks for the quick response… Yes, the values are {month,day}. The desired output is graphics - a histogram with two humps for each plant variety - one hump for the observed or calculated distribution of blooming dates, and the other for ripening dates. The two distributions is not the problem - it's the conversion of dates in Mathematica format to integers so that different years can be readily compared. I don't want to turn this into a calendar conversion problem accounting for leap years, etc. I would just like an x axis labeled with the date in a way that will be easy to read. – R. Peter DeLong Feb 26 '12 at 2:52
Maybe I should just go ahead and write a function to map: {1,x]-> x; {2,x}->31+x; {3,x}->59+x; etc. I'm just surprised that there isn't already such a function in Mathematica. – R. Peter DeLong Feb 26 '12 at 3:03

Here are two approaches.

We'll create a second dataset by shifting the given data by two months:

blossom = {{4, 3}, {4, 22}, {4, 15}, {4, 2}, {4, 18}, {4, 20}, {4,
12}, {3, 30}, {4, 4}, {4, 24}, {4, 26}, {3, 4}, {4, 26}, {4,
13}, {5, 1}, {4, 4}, {4, 8}, {4, 18}, {4, 9}, {4, 19}, {4,
10}, {4, 20}, {4, 3}, {4, 4}, {3, 21}, {4, 19}, {4, 15}, {4,
17}, {4, 9}, {4, 17}, {4, 9}, {4, 8}, {4, 23}, {4, 17}, {4,
1}, {4, 10}, {4, 15}, {4, 15}, {4, 11}, {4, 15}, {4, 19}, {4,
22}, {4, 11}, {4, 4}, {4, 12}, {3, 27}, {3, 24}, {4, 26}, {3,
28}, {4, 16}};
ripen = TranslationTransform[{2, 0}][blossom];


The first method converts the {month, day} into the number of the day in the year (1 for January 1st, 32 for February 1st, etc...) and creates a histogram from that.

DayOfYear[{m_, d_}] :=
First[DateDifference[{2011, 12, 31}, {2012, m, d}, "Day"]]

{DayOfYear[{1, 1}], DayOfYear[{2, 1}], DayOfYear[{3, 1}]}

{1, 32, 61}

Histogram[{DayOfYear /@ blossom, DayOfYear /@ ripen}, 20]


The second approach is more involved. We convert the {month, day} values into absolute times, and then use HistogramList on the combined datasets to get bins and counts without yet constructing the graphic. We then create a corresponding DateListPlot of the data, for the sole purpose of getting access to how it creates date axes. Finally we combine the ticks from the DateListPlot with an actual Histogram, reusing the bins but recalculating the bins for the different datasets, to get the final graphic.

MonthDayToTime[{m_, d_}] := AbsoluteTime[{2012, m, d}]

blossomtimes = MonthDayToTime /@ blossom;
ripentimes = MonthDayToTime /@ ripen;

{bins, counts} = HistogramList[Join[blossomtimes, ripentimes], 20]

points = Transpose[{Riffle[bins, bins], ArrayPad[Riffle[counts, counts], 1]}];
dateplot = DateListPlot[points, Frame -> False, Axes -> True, Joined -> True]

Show[Histogram[{blossomtimes, ripentimes}, {bins}], Options[dateplot, Ticks]]


-
Thanks Brett! I'm still surprised that the functions DayOfYear[ ] and its inverse are not built in to Mathematica. I especially appreciate your second suggestion and the hints about labeling the x axis. I'll use 2011 as my fake year since it is not a leap year. – R. Peter DeLong Feb 27 '12 at 0:06
Great answer, I never would have known to pull the ticks options from the DateListPlot, very smart, I would have spent forever redoing the x-axis ticks manually. – s0rce Feb 27 '12 at 3:12
You could also use DaysBetween from the Calendar package to implement DayOfYear. – Verbeia Mar 5 '12 at 21:20

DateHistogram was added in version 10.2, and uses date-specific bins and ticks.

I'll use the same {month, day} data as my other example, but instead of transforming the dates ahead of time, I can use DateFunction to provide the interpretation automatically.

blossom = {{4, 3}, {4, 22}, {4, 15}, {4, 2}, {4, 18}, {4, 20}, {4,
12}, {3, 30}, {4, 4}, {4, 24}, {4, 26}, {3, 4}, {4, 26}, {4,
13}, {5, 1}, {4, 4}, {4, 8}, {4, 18}, {4, 9}, {4, 19}, {4,
10}, {4, 20}, {4, 3}, {4, 4}, {3, 21}, {4, 19}, {4, 15}, {4,
17}, {4, 9}, {4, 17}, {4, 9}, {4, 8}, {4, 23}, {4, 17}, {4,
1}, {4, 10}, {4, 15}, {4, 15}, {4, 11}, {4, 15}, {4, 19}, {4,
22}, {4, 11}, {4, 4}, {4, 12}, {3, 27}, {3, 24}, {4, 26}, {3,
28}, {4, 16}};
ripen = TranslationTransform[{2, 0}][blossom];


### Weekly bins

DateHistogram[{blossom, ripen}, "Week",
DateFunction -> (DateObject[Prepend[#, 2015]] &)]


### Daily bins

DateHistogram[{blossom, ripen}, "Day",
DateFunction -> (DateObject[Prepend[#, 2015]] &)]


-
+1 for introducing me to a new function, even if I don't have it in 10.1. Something I wonder about is that you are giving every day a year of 2015, whereas the OP wrote: "based on actual temperature data from over 40 years" and "a more straightforward way than converting to integer dates and adjusting for leap years" -- I imagine ideally this should be plotted in sidereal time? – Mr.Wizard Feb 6 at 10:51