这里的做法是将<代码>信号(y)改动的各行之间的数值加以推断,然后为<代码>stat_smooth数据设定两个组,一个为正值数据,一个为负值,最后用新数据重新计算。
第一,我们需要用平稳数据绘制一块地块。
library(ggplot2)
library(data.table)
# library(tidyr) ## we only need tidyr::fill
## example dataset
set.seed(123)
df.ex <- data.frame(s = 1:600, l = round(rnorm(600, sd = 2), 1))
## creating the first plot with stat_smooth; same fill color for + & -
ggplot(df.ex, aes(x = s, y = l)) +
geom_point(size = 0.5, alpha = 0.6, shape = 19, color = "gray") +
geom_hline(yintercept = 0, color = "black", lwd = 0.5) +
stat_smooth(method = "loess", geom = "area", fill = "pink",
se = FALSE, linewidth = 0.5, span = 0.09,
color = "blue", alpha = 0.8) -> p; p
## ggplot build to extract the smooth data
q <- ggplot_build(p)
#> `geom_smooth()` using formula = y ~ x
smdat <- copy(q[[1]][[3]])
setDT(smdat)
## set the fill colors and group for negative and positive values
smdat[ , group := ifelse(y > 0 , 1, 2)][, fill := ifelse(y < 0 , "green", "red")]
## interpolation; taken from https://stackoverflow.com/a/27137211/6461462
smdat_grp <- smdat[ , {
ix = .I[c(FALSE, abs(diff(sign(smdat$y))) == 2)]
if(length(ix)){
pred_x = sapply(ix, function(i) approx(x = y[c(i-1, i)],
y = x[c(i-1, i)], xout = 0)$y)
rbindlist(.(.SD, data.table(x = pred_x, y = 0, group = 1, ymax = 0),
data.table(x = pred_x, y = 0, group = 2, ymax = 0)),
fill = TRUE)} else .SD}][order(x)]
## filling the NA values in the remaining columns
lapply(split(smdat_grp, smdat_grp$group), (dat)
tidyr::fill(dat, everything(), .direction = "downup")) |>
rbindlist() |>
as.data.frame() -> q[[1]][[3]]
## plot the modified ggplot
pq <- ggplot_gtable(q)
plot(pq)
smoothed_values <- predict(loess(l ~ s, data = df.ex, span = 0.09))
fill_color <- ifelse(smoothed_values >= 0, "red", "green")
ggplot(df.ex, aes(x = s, y = l)) +
geom_point(size = 0.5, alpha = 0.6, shape = 19, color = "gray") +
ggbraid::geom_braid(aes(s, ymin = 0, ymax = smoothed_values, fill = fill_color),
alpha = 0.5, lwd = 0.5, color = "gray3") +
geom_hline(yintercept = 0, lwd = 0.25, color = "black") +
geom_smooth(method = "loess", se = FALSE, linewidth = 1, span = 0.09) +
theme(legend.position = "none") +
coord_cartesian(ylim = c(-1, 1)) ## zoom to see the difference
#> `geom_braid()` using method = line
#> `geom_smooth()` using formula = y ~ x
https://i.imgur.com/320N398.png” alt=">
Created on 2024-03-07 with reprex v2.0.2.