Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'd like to control more aspects of a DateListPlot, for example: shading for weekend days, and/or indicators for daytime/nighttime areas.

By way of illustration, here's a simple example of a set of time data points (recent questions on mathematica.stackexchange):

questions = 
  First[Rest[
    Import["http://api.stackexchange.com/2.0/questions?page=1&\
pagesize=100&order=desc&sort=creation&site=mathematica", "JSON"]]];

questionTimes = 
  Cases[questions, HoldPattern["creation_date" -> value_] :>  value, 
   Infinity];

hours = (Mod[#, 86400] /86400) 24  & /@ questionTimes ;

DateListPlot[Transpose[{questionTimes, hours}], Filling -> Bottom, 
 GridLines -> False, Frame -> {True, True, False, False}]

and the plot is like this:

stack exchange

I can't see how to show the necessary information along the x-axis, nor how to shade different areas of the graph to show day/night.

Edit: I now realise that the date/times returned by the SE API are in Unix Epoch (1970), and I hadn't noticed because I wasn't able to see the day numbers or years on my first attempt at a plot...

share|improve this question
add comment

2 Answers

up vote 7 down vote accepted

Somehow DateListPlot is resistant to many styling options. Without fiddling with the internals, here is a starting point.

WeekendQ[date_] := 
 With[{d = DateString[date, "DayName"]}, 
  MatchQ[d, "Saturday" | "Sunday"]]
weekStyle = {Blue};
weekendStyle = {PointSize -> .015, Directive[Red]};
styleList = 
  Map[If[WeekendQ[#], weekendStyle, weekStyle] &, questionTimes];
DateListPlot[Partition[Transpose[{questionTimes, hours}], 1],
 PlotStyle -> styleList, Filling -> Bottom, GridLines -> False,
 FillingStyle -> ColorData[1][1],
 Frame -> {True, True, False, False},
 PlotRange -> {0, 24}, 
 Prolog -> {LightGray, Rectangle[Scaled[{0, 0}], Scaled[{1, 6/24}]], 
  Rectangle[Scaled[{0, 20/24}], Scaled[{1, 1}]]}]

Looks like:

enter image description here

share|improve this answer
    
Thanks, this is great! I hadn't made the connection with PlotStyle (still getting used to the wily ways of the Mathematica help) ... Just wondering whether your "May 02" entries are due to the use of Unix Epoch timestamps or different time zones... I'm trying to add "+ AbsoluteTime["January 1, 1970"]" to fix. :) –  cormullion May 1 '12 at 16:06
add comment

Here is an alternative approach which uses colour coding of date labels to indicate Weekday/Weekend ( Green/Red ) and colour shade to indicate daytime/nightime ( Lighter/Darker ).

I've dropped some of the points and applied a minimum separation to help make the plot more legible in the limited display space here.

Functions

(* Check for the type of day of the week *)
WeekdayQ[dateString_String] := With[{weekend = {"Sat", "Sun"}}, 
  And @@ (StringFreeQ[dateString, #] & /@ weekend)]

(* Check for time of day, adjust for time of year and location *)
DaytimeQ[dateString_String] := With[{daylight = Range[8, 18]}, 
  MemberQ[daylight, (DateList@dateString)[[4]]]]

(* Apply colour adjustments to date strings to reflect weekday/time *)
ColorizeDate[dateString_String] := Style[dateString, 
  If[DaytimeQ@dateString, Lighter, Darker]@
   If[WeekdayQ@dateString, Darker@Green, Red]]

(* Ease points apart enough to make the text legible  *)
Options[Relax]={MinSeperation->0.03};
Relax[data_,OptionsPattern[]]:=With[{sep=OptionValue@MinSeperation(Max@data-Min@data)},
Flatten[{First@data,First@data +Accumulate[If[#<sep, sep,#]&@Differences@data]}]]

Prep data for plotting

(* points thinned to allow plot to be readable within the online space constraints *)
questionTimes = 
  Reverse@Cases[questions, 
     HoldPattern["creation_date" -> value_] :> value, 
     Infinity][[Select[Range@Length@questions[[2]], OddQ]]];

shift = DateDifference[{1900, 1, 1}, {1970, 1, 1}]*24*60*60;

hours = (Mod[#, 86400]/86400) 24 & /@ questionTimes;

questionData = {ToDate /@ (questionTimes+shift), hours}\[Transpose];

Plot the data

With[{labels = 
   Rotate[ColorizeDate@DateString@#, (3 \[Pi])/2] & /@ questionData[[All, 1]], 
  softCoords = Relax[AbsoluteTime /@ questionData[[All, 1]], MinSeperation -> 0.01]}, 
 ListPlot[{softCoords, questionData[[All, 2]]}\[Transpose], 
  Ticks -> {{softCoords, labels}\[Transpose], Automatic}, 
  Filling -> Axis, AxesOrigin -> {First@softCoords, 0}]]

Mathematica graphics

share|improve this answer
    
If anyone can work out how to easily extend the colouring to the points and fill lines, I think that would make a nice option. –  image_doctor May 1 '12 at 14:04
    
coloring the points can be done with PlotStyle. I didn't manage to specify separate filling styles though. –  Markus Roellig May 1 '12 at 14:10
    
@image_doctor Thanks, nice solution. I'm currently working out how to make it show today's date... :) –  cormullion May 1 '12 at 16:07
    
@cormullion How about this: shift = DateDifference[{1900, 1, 1}, {1970, 1, 1}]*24*60*60; Then add that to your time value. –  image_doctor May 1 '12 at 16:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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