0

I have a DF with 4 columns: date, original, predicted and change. I would like to make an area graph and the values that are negative are red and the positive ones are green according to the change column.

My code:

data %>% 
  filter(variaveis == c("diferenca.em.pontos")) %>%
  mutate(change = ifelse(value > 0, "positive", "negative")) %>%
  ggplot(aes(x = Período, y = value, fill = change)) +
  geom_area() +
  geom_hline(yintercept = 0)

But it's returning like this, with this green line above the red values, and this was not supposed to happen. What am I doing wrong?

enter image description here

If I use geom_col instead of geom_area, the graph is right:

enter image description here

My dput:

structure(list(Período = structure(c(13453, 13483, 13514, 13545, 
13573, 13604, 13634, 13665, 13695, 13726, 13757, 13787, 13818, 
13848, 13879, 13910, 13939, 13970, 14000, 14031, 14061, 14092, 
14123, 14153, 15918, 15949, 15979, 16010, 16040, 16071), class = "Date"), 
    variaveis = structure(c(5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 
    5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 
    5L, 5L, 5L, 5L, 5L, 5L), .Label = c("Brasil", "Brasil.predicted", 
    "Brasil.nivel", "Brasil.predicted.nivel", "diferenca.em.pontos"
    ), class = "factor"), value = c(28.5307986472031, 22.8246389177625, 
    16.3033135126875, 6.52132540507499, 4.07582837817188, -12.2274851345156, 
    -10.5971537832469, -8.96682243197813, -6.521325405075, -4.89099405380624, 
    -11.4123194588812, -20.3791418908594, -8.96682243197812, 
    -10.5971537832469, -9.7819881076125, -6.521325405075, 0, 
    -8.15165675634375, -27.7156329715687, -43.2037808086219, 
    -34.2369583766437, -26.9004672959344, -17.9336448639562, 
    -38.3127867548156, -18.7488105395906, -25.2701359446656, 
    -21.1943075664937, -14.6729821614187, -8.15165675634375, 
    0.815165675634374), change = c("positive", "positive", "positive", 
    "positive", "positive", "negative", "negative", "negative", 
    "negative", "negative", "negative", "negative", "negative", 
    "negative", "negative", "negative", "negative", "negative", 
    "negative", "negative", "negative", "negative", "negative", 
    "negative", "negative", "negative", "negative", "negative", 
    "negative", "positive")), row.names = c(1L, 2L, 3L, 4L, 5L, 
6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 
19L, 20L, 21L, 22L, 23L, 24L, 82L, 83L, 84L, 85L, 86L, 87L), class = "data.frame")
  • The issue is that `geom_area` is basically a kind of `geom_line`. Therefore the data points per group get connected. – stefan Aug 13 '20 at 17:12
  • There is no way to draw a graph in that way that I mentioned? – Alexandre Sanches Aug 13 '20 at 19:16
  • There is a way, but it would probably be best to use `geom_ribbon` instead. To get it to work, you need to compute a `ymin` and a `ymax` for each x value and fill color. – statstew Aug 14 '20 at 03:12
  • `geom_area` is a blend between `geom_line` and `geom_ribbon`. It connects observations in the order of the x variable, but specifies one of the `ymin`/`ymax` variables as zero. – statstew Aug 14 '20 at 03:16
  • 3
    You can try adding `tidyr::complete(change, Período, fill = list(value = 0))` as the final part of your data-preprocessing before piping the results to `ggplot`. This adds 0 values in between. – Z.Lin Aug 14 '20 at 04:15
  • @Z.Lin this works, thank you! Add an answer and I'll accept it. – Alexandre Sanches Aug 14 '20 at 11:23

1 Answers1

2

Instead of trying to plot everything in the same geom_area() function, try to use it twice: one for the positive values and another for the negative ones. Probably not the best solution but it works.

ggplot(dput) +
geom_area(aes(x=Período, y=ifelse(value<0, value,0)), fill="red") +
geom_area(aes(x=Período, y=ifelse(value>0, value, 0)), fill="green")

Resulting plot with dput

I hope this has helped you :)

jmt
  • 21
  • 3