1

Given a standardized time series, I will like to shade positive and negative areas in blue and red colors, respectively. Gaining inspiration from the following post, I tried the following:

library (ggplot2)
ggplot(b, aes(dates, dat)) + geom_area(data=subset(b, dat<=0),fill="red",position = 'identity') + geom_area(data=subset(b, dat>=0), fill="blue",position = 'identity')+ 
 geom_smooth(method = "lm",se=F,size=1.2)+geom_line(aes(colour = "red"),size=0.5)+
 scale_x_date(breaks = seq(as.Date("1951-01-01"), as.Date("2013-12-31"), by="10 years"), 
              labels=date_format("%Y"))+theme(axis.text.x  = element_text(angle=0, vjust=0.5, size=10))+
 scale_y_continuous(limits=c(-3,3),breaks = seq(-3,3, by = 1))+ylab(NULL) + xlab("Time (year)")

enter image description here

The shadded areas do not follow the geom_line correctly. Even at that, the area looks awkward.

How can one fill the area under the geom_lines in a neat way?

Sample data:

    b= structure(list(dates = structure(c(-6940, -6909, -6881, -6850, 
-6820, -6789, -6759, -6728, -6697, -6667, -6636, -6606, -6575, 
-6544, -6515, -6484, -6454, -6423, -6393, -6362, -6331, -6301, 
-6270, -6240, -6209, -6178, -6150, -6119, -6089, -6058, -6028, 
-5997, -5966, -5936, -5905, -5875, -5844, -5813, -5785, -5754, 
-5724, -5693, -5663, -5632, -5601, -5571, -5540, -5510, -5479, 
-5448, -5420, -5389, -5359, -5328, -5298, -5267, -5236, -5206, 
-5175, -5145, -5114, -5083, -5054, -5023, -4993, -4962, -4932, 
-4901, -4870, -4840, -4809, -4779, -4748, -4717, -4689, -4658, 
-4628, -4597, -4567, -4536, -4505, -4475, -4444, -4414, -4383, 
-4352, -4324, -4293, -4263, -4232, -4202, -4171, -4140, -4110, 
-4079, -4049, -4018, -3987, -3959, -3928), class = "Date"), dat = c(-0.910625605549408, 
-0.965393470171649, -1.09716673692565, -1.11364372522414, -0.966928227483839, 
-0.910113178396864, -0.630295785110983, -0.195304139966426, -0.135086300125106, 
-0.125590841642733, -0.137958304991406, 0.0292016064073559, 0.076904806101527, 
0.0978149453048161, 0.155702136185981, 0.487748711269244, 0.819056198490012, 
0.885907744155614, 0.639001596177642, 0.122744861489825, -0.0535439932455298, 
0.00848176075044228, -0.0256120780520969, -0.268691565651955, 
-0.261482420394633, -0.261118385414154, -0.250228992827904, -0.219694376386043, 
-0.660730544599343, -0.879357276742173, -0.836054538921174, -0.0247531668208166, 
0.341918262849067, 0.326418683049986, 0.41600402395692, 0.818673624667216, 
0.956600038145188, 0.868547394585506, 0.962924798622049, 0.507840261383761, 
0.555739351610198, 0.333775341549737, 0.818872529340592, 1.3044454120894, 
1.36146482036678, 1.67015073361349, 1.74841533722962, 1.65069696771922, 
1.57425380503261, 1.57750737078759, 1.60470949976585, 1.76584338785841, 
1.78747286516521, 2.04291142516622, 1.65691986614514, 0.83435364531951, 
0.366895222917817, 0.106061443191605, -0.0136257949563308, -0.039172450722867, 
-0.106395821358355, -0.109865867287957, -0.140110797453417, -0.233859633193537, 
-0.524821103280969, -0.475822623121396, -0.091938340606421, -0.312738655577179, 
-0.218992519559913, -0.41729583138858, -0.341109703626088, -0.178764615943057, 
-0.10437976030027, -0.127138438602851, -0.329999135840519, -0.441987514925649, 
-0.347126807394235, -0.685007291681231, -1.31251477363399, -1.16026862098407, 
-0.857848717241228, -0.719142935845841, -0.843613199408936, -0.88500351882596, 
-0.916860816746853, -0.831325622290225, -0.851113829318015, -0.982876516574583, 
-0.821655087299125, -0.725824711405517, -0.605505392406424, -0.419847379860051, 
-0.614459124334038, -0.323828057338646, -0.257470581680261, -0.243811093634083, 
-0.210160321834246, -0.17882228119167, 0.100567046322816, 0.333897813715549
)), .Names = c("dates", "dat"), row.names = c(NA, 100L), class = "data.frame")

This is the same figure plotted within MATLAB and can be found here. Solutions outside ggplot2 are also welcome.

The same figure plotted in MATLAB with anomaly function

enter image description here

code123
  • 2,082
  • 4
  • 30
  • 53
  • Did you consider using `geom_bars` for those fills? – Deena Jan 09 '18 at 22:08
  • 1
    Possible duplicate of [How to fill geom_polygon with different colors above and below y = 0?](https://stackoverflow.com/questions/27135962/how-to-fill-geom-polygon-with-different-colors-above-and-below-y-0) – Henrik Jan 09 '18 at 22:09
  • @Henrik Thanks for the link. However, the boundaries of `geom_area` are still pretty rough for publication standard. How can one fill the area under curve and keep the variation of the lines in tact. – code123 Jan 10 '18 at 15:56
  • @code123 Thanks for your feedback. In the first comment under my linked answer, you see that OP experienced some quality issues as well. In my comment (now deleted) I suggested that the plot should be saved to e.g. PDF and the quality should be judged there, not in Rstudio. In the saved file the quality was just fine, and it turned out that the plot was rendered poorly only in RStudio. Please give it a try! Cheers. – Henrik Jan 10 '18 at 16:40
  • @Henrik can you try your solution on my data? I tried it but the plot still looks really not good for publication. Those shapes created by `geom_area` do not represent what `geom_line` is plotting. – code123 Jan 10 '18 at 18:32
  • Then please try to make a _minimal_ example, show what you have tried, and explain where it fails. In my answer, I demonstrated that the method worked on a data set with 6 rows. _If_ it works on 6 rows, it works on 60, or 756. If it _fails_, it is much easier to spot the cause of the problem and play around with solutions using a _minimal_ data set. – Henrik Jan 10 '18 at 18:46
  • @Henrik I just added a minimal data set. Thanks. – code123 Jan 11 '18 at 01:54

1 Answers1

0

After a few struggles, I think this should be appropriate for my case, although not the best. Instead of geom_area, I used geom_linearrange:

ggplot(b, aes(dates, dat, ymin = 0,ymax = dat)) + geom_linerange(data = b, aes(colour = ifelse(dat <0, "blue", "red")),stat = "identity",
                                                                 position = "identity",size=0.5)

and the result is below. It looks better than my previous plot and is similar to that plotted within MATLAB. You can play with the line size to get more density as needed.

enter image description here

code123
  • 2,082
  • 4
  • 30
  • 53