admin管理员组

文章数量:1427881

How can I modify my ggplot2 code so that the ribbon fill appears only when VAL ≤ -1 for at least two consecutive months and does not extend beyond VAL > -1?

Dummy data:

library(tibble)
library(lubridate)

dates <- seq(from = as.Date("1997-01-01"), to = as.Date("1998-12-01"), by = "month")
dummy <- tibble(
  Date = rep(dates, each = 6),  # 2 AREA × 3 METRIC = 6 baris per bulan
  AREA = rep(c("NORTHERN", "SOUTHERN"), each = 3, times = length(dates)),
  Year = year(rep(dates, each = 6)),
  GROUP = paste(year(rep(dates, each = 6)), year(rep(dates, each = 6)) + 1, sep = "/"),
  METRIC = rep(c("SPI3", "SPI6", "SPI12"), times = length(dates) * 2),
  VAL = round(runif(length(dates) * 6, -3.5, 3.5), 2),  # SPI acak antara -3.5 hingga 3.5
  ID = ifelse(round(runif(length(dates) * 6, -3.5, 3.5), 2) <= -1, "DROUGHT", "NOT-DROUGHT"),
  fill_color = ifelse(round(runif(length(dates) * 6, -3.5, 3.5), 2) <= -1, "red", "gray")
)

Plot:

ggplot(data = spi_df, aes(x = Date, y = VAL, col = AREA, group = AREA)) +
  geom_line() +  
  geom_ribbon(data = spi_df%>%filter(VAL<=-1),
              aes(x=Date,ymin = VAL, ymax = -1, group = AREA), 
              fill = "red, colour= "transparent",linetype = 0,
              alpha = 0.3) + 
  facet_grid(~METRIC~GROUP, scales = "free_x") +
  coord_cartesian(expand = FALSE) +
  theme_bw() +
  labs(y = "SPI") +
  scale_y_continuous(breaks = seq(-4, 4, 1), limits = c(-4, 4)) +
  theme(legend.position = "bottom")  

How can I modify my ggplot2 code so that the ribbon fill appears only when VAL ≤ -1 for at least two consecutive months and does not extend beyond VAL > -1?

Dummy data:

library(tibble)
library(lubridate)

dates <- seq(from = as.Date("1997-01-01"), to = as.Date("1998-12-01"), by = "month")
dummy <- tibble(
  Date = rep(dates, each = 6),  # 2 AREA × 3 METRIC = 6 baris per bulan
  AREA = rep(c("NORTHERN", "SOUTHERN"), each = 3, times = length(dates)),
  Year = year(rep(dates, each = 6)),
  GROUP = paste(year(rep(dates, each = 6)), year(rep(dates, each = 6)) + 1, sep = "/"),
  METRIC = rep(c("SPI3", "SPI6", "SPI12"), times = length(dates) * 2),
  VAL = round(runif(length(dates) * 6, -3.5, 3.5), 2),  # SPI acak antara -3.5 hingga 3.5
  ID = ifelse(round(runif(length(dates) * 6, -3.5, 3.5), 2) <= -1, "DROUGHT", "NOT-DROUGHT"),
  fill_color = ifelse(round(runif(length(dates) * 6, -3.5, 3.5), 2) <= -1, "red", "gray")
)

Plot:

ggplot(data = spi_df, aes(x = Date, y = VAL, col = AREA, group = AREA)) +
  geom_line() +  
  geom_ribbon(data = spi_df%>%filter(VAL<=-1),
              aes(x=Date,ymin = VAL, ymax = -1, group = AREA), 
              fill = "red, colour= "transparent",linetype = 0,
              alpha = 0.3) + 
  facet_grid(~METRIC~GROUP, scales = "free_x") +
  coord_cartesian(expand = FALSE) +
  theme_bw() +
  labs(y = "SPI") +
  scale_y_continuous(breaks = seq(-4, 4, 1), limits = c(-4, 4)) +
  theme(legend.position = "bottom")  

Share Improve this question edited Mar 16 at 19:23 marc_s 756k184 gold badges1.4k silver badges1.5k bronze badges asked Mar 16 at 16:56 Rahmat HidayatRahmat Hidayat 476 bronze badges 1
  • Inconsistent reprex, please try the reprex you give us in a fresh R session to make sure it works for us: 'spi_df' not found; unmatched quotes; your plot is a bit different from what this code produces. – r2evans Commented Mar 16 at 18:50
Add a comment  | 

1 Answer 1

Reset to default 2

Fixing two things with your sample code: spi_df to dummy, and repairing the unmatched quotes ...

After that, I suggest the first step is to add in columns that only have data when it matches your condition of < -1. This is a first step; while it is a first step, it does show one weakness: your data is discrete not truly continuous, so the red ribbons do not flow up the sloped line when the next point exceeds -1.

dummy |>
  arrange(Date) |>
  mutate(VAL_neg = if_else(VAL <= -1, VAL, NA)) |>
  mutate(
    .by = c(METRIC, GROUP, AREA),
    VAL_neg_grp = consecutive_id(is.na(VAL_neg))
  ) |> 
  mutate(
    .by = c(METRIC, GROUP, AREA, VAL_neg_grp),
    VAL_neg = if (n() > 1) VAL_neg else NA
  ) |>
  ggplot(aes(x = Date, y = VAL, col = AREA, group = AREA)) +
  geom_line() +  
  geom_ribbon(aes(x=Date, ymin = VAL_neg, ymax = -1, group = paste(AREA, VAL_neg_grp)), 
              # notice the "~" for filtering of current data, not original `dummy`
              data = ~ filter(.x, !is.na(VAL_neg)),
              fill = "red", colour= "transparent",linetype = 0,
              alpha = 0.3, na.rm = TRUE) + 
  facet_grid(~METRIC~GROUP, scales = "free_x") +
  coord_cartesian(expand = FALSE) +
  theme_bw() +
  labs(y = "SPI") +
  scale_y_continuous(breaks = seq(-4, 4, 1), limits = c(-4, 4)) +
  theme(legend.position = "bottom")  

If your intent is to have the ribbons follow the AREA lines up the slopes, you'll need to add rows based on interpolated (fractional) Date values. It's not impossible but a bit more work and I wasn't certain you needed it.

本文标签: rgeomribbon with specific conditionStack Overflow