7
$\begingroup$

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}
}
$\endgroup$
6
  • $\begingroup$ Please include an example of the output you desire. $\endgroup$
    – Mr.Wizard
    Commented Feb 26, 2012 at 1:49
  • $\begingroup$ For example, there is a question right below yours that includes how to create this: i.sstatic.net/r9uMh.png $\endgroup$
    – Mr.Wizard
    Commented Feb 26, 2012 at 1:51
  • $\begingroup$ Are those values {month, day}? $\endgroup$ Commented Feb 26, 2012 at 2:41
  • $\begingroup$ 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. $\endgroup$ Commented Feb 26, 2012 at 2:52
  • $\begingroup$ 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. $\endgroup$ Commented Feb 26, 2012 at 3:03

2 Answers 2

11
$\begingroup$

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]

enter image description here


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]]

enter image description here

$\endgroup$
3
  • $\begingroup$ 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. $\endgroup$ Commented Feb 27, 2012 at 0:06
  • $\begingroup$ 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. $\endgroup$
    – s0rce
    Commented Feb 27, 2012 at 3:12
  • $\begingroup$ You could also use DaysBetween from the Calendar package to implement DayOfYear. $\endgroup$
    – Verbeia
    Commented Mar 5, 2012 at 21:20
5
$\begingroup$

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]] &)]

enter image description here

Daily bins

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

enter image description here

$\endgroup$
1
  • $\begingroup$ +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? $\endgroup$
    – Mr.Wizard
    Commented Feb 6, 2016 at 10:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.