1

I would like to plot my data, highlighting the positive and negative values ("firebrick" and "dodgerblue4"respectively) and create a legend with 'Upwelling' being the positive values and "Downwelling" the negative values. My code now looks like this:

ggplot(dados19,aes(Date,UI))+
  geom_line()+
  ggtitle("Upwelling Index during the period 2012-2019")+
  theme(plot.title = element_text(hjust = 0.5))+
  xlab("Year") + ylab("Upwelling index")


A tibble: 10,225 x 2
     UI   Date               
   <dbl> <dttm>             
   37.9  2012-01-01 00:00:00
    9.18 2012-01-01 06:00:00
    1.18 2012-01-01 12:00:00
   27.0  2012-01-01 18:00:00
 -292.   2012-01-02 00:00:00
   98.2  2012-01-02 06:00:00
   95.9  2012-01-02 12:00:00
    6.19 2012-01-02 18:00:00
   -4.65 2012-01-03 00:00:00
   40.1  2012-01-03 06:00:00
# ... With 10,215 more rows

The best way to represented was using gradient

scale_color_gradient(low = "dodgerblue4",high = "firebrick")+

And the plot was like this: enter image description here

I need the same plot but with only the 2 colors (red for positive values and blue for negative values), not a gradient.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
macs2021
  • 85
  • 1
  • 7
  • Welcome to SO! To help us to help you could you please add your **data** as a `dput()`? See [how to make a minimal reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). Simply type `dput(NAME_OF_DATASET)` into the console and copy & paste the output starting with `structure(....` into your post. If your dataset has a lot of observations you could do `dput(head(NAME_OF_DATASET, 20))` for the first twenty rows of data. – stefan Jan 19 '21 at 10:24

3 Answers3

2

Given a reproducible example:

dados19 <- tibble::tribble(~UI    , ~Date,
                             37.9 , "2012-01-01 00:00:00",
                              9.18, "2012-01-01 06:00:00",
                              1.18, "2012-01-01 12:00:00",
                             27.0 , "2012-01-01 18:00:00",
                           -292.  , "2012-01-02 00:00:00",
                             98.2 , "2012-01-02 06:00:00",
                             95.9 , "2012-01-02 12:00:00",
                              6.19, "2012-01-02 18:00:00",
                             -4.65, "2012-01-03 00:00:00",
                             40.1 , "2012-01-03 06:00:00")

dados19$Date <- lubridate::as_datetime(dados19$Date)

You could proceed as follow:

library(ggplot2)

ggplot(dados19, aes(Date, UI)) +
 geom_line() +
 geom_point(aes(colour = factor(sign(UI))), size = 3) +
 scale_colour_manual(values = c("firebrick", "black", "dodgerblue4"),
                     breaks = c("-1", "0", "1"),
                     labels = c("Downwelling", "Stationary", "Upwelling")) +
 labs(title = "Upwelling Index during the period 2012-2019",
      x = "Year",
      y = "Upwelling index",
      colour = "Up/Down") +
 theme(plot.title = element_text(hjust = 0.5))

enter image description here

I didn't know if you wanted some coloured points or bars..

I've added a geom_points instruction to add the feature you wanted.

Note that colour = defines the colour of the points. I've set it equal to the sign of UI as you requested. I had to force it into a factor so that it will provide two separate colours (instead of a gradient).

Finally, I've used scale_colour_manual to set the colours you wanted. sign returns only 3 values: -1, 0, 1. You did not provide a colour for the zero scenario, therefore I set "black", but you can change it. With labels you can replace -1, 0, 1 with the text you want.

Edo
  • 7,567
  • 2
  • 9
  • 19
  • Thank you! I tried with the points but because the dataset is so big the visualization does not look so good with the lines in blacks. I was hoping to get the lines colored. Tried with a bar plot but did not look so good either. – macs2021 Jan 19 '21 at 11:10
2

Actually you are already very close to the desired output as you expected. What you need might be adding one more line geom_point(aes(color = UI > 0)) like below

ggplot(dados19, aes(Date, UI)) +
    geom_point(aes(color = UI > 0)) +
    geom_line() +
    ggtitle("Upwelling Index during the period 2012-2019") +
    theme(plot.title = element_text(hjust = 0.5)) +
    xlab("Year") +
    ylab("Upwelling index")

enter image description here

ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
  • Thank you! I tried with the points but because the dataset is so big the visualization does not look so good with the lines in blacks. I was hoping to get the lines colored. Tried with a bar plot but did not look so good either. – macs2021 Jan 19 '21 at 11:10
1

Here is a solution that draws segments for positive and negative values of the y axis variable with different colors. If uses an auxiliary function to find the cut points, meaning, the zeros of the segments defined by end points with different signs.

lin_zeros <- function(data, x, y){
  xname <- deparse(substitute(x))
  yname <- deparse(substitute(y))
  x <- data[[xname]]
  y <- data[[yname]]
  ix <- which(c(FALSE, abs(diff(sign(y))) == 2))
  res <- lapply(ix, function(i) approx(x = y[c(i - 1, i)], y = x[c(i - 1, i)], xout = 0))
  res <- do.call(rbind.data.frame, res)
  res <- res[2:1]
  row.names(res) <- NULL
  names(res) <- c(xname, yname)
  res
}

Now the plot.

library(dplyr)
library(ggplot2)

dados19 %>%
  bind_rows(dados19 %>% 
              lin_zeros(Date, UI) %>%
              mutate(Date = as.POSIXct(Date, origin = "1970-01-01"))) %>%
  arrange(Date) %>%
  mutate(xend = lead(Date),
         yend = lead(UI, default = 0)) %>%
  mutate(line_color = (UI == 0 & yend < 0) | (UI < 0 & yend == 0)) %>%
  mutate(Index = ifelse(line_color, "Downwelling", "Upwelling"),
         Index = factor(Index)) %>%
  select(-line_color) %>% 
  ggplot(aes(Date, UI, color = Index)) +
  geom_segment(aes(xend = xend, yend = yend)) +
  scale_color_manual(breaks = c("Downwelling", "Upwelling"),
                     values = c("dodgerblue4", "firebrick")) +
  ggtitle("Upwelling Index during the period 2012-2019") +
  xlab("Year") + 
  ylab("Upwelling index") +
  theme(plot.title = element_text(hjust = 0.5))

enter image description here

Rui Barradas
  • 70,273
  • 8
  • 34
  • 66
  • Hello! First thank you for the reply, but I am running the script and the graphic is all red. Do you know what might be happening? – macs2021 Jan 22 '21 at 00:03
  • This is magic, `which(c(FALSE, abs(diff(sign(y))) == 2))`, love your function! – M.Viking Feb 17 '21 at 17:18