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 want to create a plot showing historical annual maximum and minimum temperatures. I've figured out how to get 10 years of historical temperature data from Wolfram|Alpha. The plot below shows the highest, average high, average low, and lowest temperature during the past ten years for Austin, Tx. The problem occurs when I try to use ColorFunction to control the filling color.

image

The code below returns a relatively small amount of data that can be used to replicate the problem.

max = Map[#*9/5+32.&, WeatherData["KATT","MaxTemperature",{{2011,1,1},{2011,12,31},"Week"}][[All,2]]];  
min = Map[#*9/5+32.&, WeatherData["KATT","MinTemperature",{{2011,1,1},{2011,12,31},"Week"}][[All,2]]];    

DateListPlot[{max, min},{{2011,1,1},Automatic,"Week"},Joined->True, Filling->{1->{2}}, ColorFunction ->"Rainbow"]   

I would like to have simple a vertical color gradient. Instead, the fill color is a more complicated function of the top curve and the y-axis. I can't describe it properly, but hopefully, the problem is apparent. I've tried several approached to controlling the fill color, but none of them do what I want, and most of them don't work at all.

image

I would ultimately like to use slightly different filling styles between the highest ever and average highest temperature, and between the average lowest and lowest ever - perhaps less opaque, and for the four plot lines to still be visible.

share|improve this question
    
"I want the same color to appear at a particular temperature level across the plot, and the color also to be a function of y-axis (corresponding to the temperature in some understandable manner)." So, you want a vertical color gradient? –  VF1 Dec 1 '12 at 2:03
    
in the y direction the fill seems to Blend the two colours ColorData["Rainbow",y_top] and ColorData["Rainbow",y_bottom] instead of giving a gradient. Maybe someone else can comment whether that is intended behaviour. –  Mike Honeychurch Dec 1 '12 at 2:17
    
@MikeHoneychurch @GeorgeWolfe the issue at hand is that ColorFunction only looks at the points actually plotted out by DateListPlot, and so, since Filling doesn't actually sample every point between the two list plots, we'd have no way of assigning a y-dependent color value to each point in between the list plot lines. I believe there is no solution to this using the DateListPlot options. There is however, hope that we can solve this by extracting the Polygon that is made by Filling and artificially coloring that... –  VF1 Dec 1 '12 at 2:24
    
@MikeHoneychurch Wow. Much tricker than I thought! It seems like this is would be a common use of fill color. –  George Wolfe Dec 1 '12 at 2:27
    
A bit of a fix about filling is that FillingStyle -> (Sow[#] &) returns a Polygon with no significant information about where its points are. –  VF1 Dec 1 '12 at 2:28
show 1 more comment

2 Answers 2

up vote 8 down vote accepted

This is more complicated than you would think is needed but I think this is what you are looking for (re: for your output)

  Overlay[{
  DensityPlot[y, {x, 0, 1}, {y, 0, 100},
   AspectRatio -> 2/5,
   ColorFunction -> ColorData["Rainbow"],
   ColorFunctionScaling -> True,
   Frame -> False,
   ImageSize -> {535, 235},
   ImagePadding -> {{30, 5}, {30, 5}},
   PlotRange -> Automatic,
   PlotRangePadding -> 0],

  DateListPlot[{max, min}, {{2011, 1, 1}, Automatic, "Week"},
   AspectRatio -> 2/5,
   Background -> None,
   Filling -> {1 -> Top, 2 -> Bottom},
   FillingStyle -> White,
   GridLines -> None,
   Joined -> True,
   ImageSize -> {535, 235},
   ImagePadding -> {{30, 5}, {30, 5}},
   PlotRangePadding -> 0,
   PlotStyle -> None]
  }]

enter image description here

This is overlaying two plots that you should be familiar with re: how to tweek options.

share|improve this answer
    
I came up with this: Polygon[#1~Join~Reverse[#2] & @@ Reap[DateListPlot[{max, min}, {{2011, 1, 1}, Automatic, "Week"}, Joined -> True]/. Line[a_] :> (Sow[a]; Line[a])][[-1, -1]]], but then I realized that you can't color a gradient on a Graphics. I was going to use a DensityPlot, but then I saw you beat me to it. +1 –  VF1 Dec 1 '12 at 2:43
    
@Mike Honeychurch Thanks, Mike. That is what I want to do. –  George Wolfe Dec 1 '12 at 2:47
    
@VF1 there may be other ways but I couldn't think of any offhand. –  Mike Honeychurch Dec 1 '12 at 2:48
add comment

This is a followup to show how @Mike Honeychurch and @VF1 suggestions worked. I found that I needed to use three overlays to get the effect I wanted: a density plot for the color, a DateListPlot to show the plotlines, and another DateListPlot with no graphs to properly display Epilog text and other lines. I'm not completely finished with the plot, but here is how it looks so far:

image

To complete the story, here is how I cleaned and date aligned 10 years of temperature data from the Wolfram|Alpha:

max = WeatherData["KATT","MaxTemperature", {{2000, 1, 1}, {2011, 12, 31}, "Day"}];
max = Delete[max, Position[max[[All, 1, 2 ;; 3]], {2, 29}]]; (*drop Feb 29ths*)
max[[All, 2]] = Map[ # *9/5 + 32. & , max[[All, 2]]] (*convert to fahrenheit*)
maxtable = lineUpByDay[max]; (*date align - code below*)
avemax = Map[average, Transpose[maxtable]]; (*average by day-code below*)  
maxmax = Map[maximum, Transpose[maxtable]]; (*record high by day-code below*) 

Wolfram|Alpha returned data that had gaps (days without data). To create a date-aligned table I used a procedure:

lineUpByDay[list_] := Module[{days, years, temptable},
days = Union[list[[All, 1, 2 ;; 3]]];
years = Union[list[[All, 1, 1]]];
temptable = Table["", {r, Length[years]}, {c, Length[days]}];
Do[
   r = Position[years, list[[i, 1, 1]]][[1, 1]];
   c = Position[days, list[[i, 1, 2 ;; 3]]][[1, 1]];
   temptable[[r, c]] = list[[i, 2]], {i, 1, Length[list]}];
   temptable
 ]  

And to get the average and maximum temperature for each day I mapped the following over maxtable:

average[list_] := Module[{x}, x = Cases[list, _Real]; Total[x]/Length[x]]
maximum[list_] := Module[{x}, x = Cases[list, _Real]; Max[x]]  

I did something similiar with "MinTemperature" for the average low and record low. It's not clever, but fast and satisfactory.

share|improve this answer
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.