Как я могу сделать высоту барплота зависимой от значения функции на том же графике? - PullRequest
0 голосов
/ 09 октября 2019

У меня есть гистограмма с накоплением и линейный график на том же графике, как вы можете видеть на первом (самом верхнем) рисунке.

Я собираюсь добавить еще одну функциональность. Всякий раз, когда красная область находится полностью ниже красной линии, я хотел бы показать горизонтальную проекцию этой области на красной линии и закрасить эту часть фиолетовым, как вы можете видеть на втором рисунке.

Однако, как бы я ни пытался, я столкнулся со следующими проблемами:

  • Как точно раскрасить до красной кривой без видимого наложения?
  • Каксделать все под областью интересов прозрачным? (В этом случае фиолетовая окраска не должна существовать ниже y = 0,70.)

Самое близкое, что я мог получить, это добавить дополнительную фиолетовую полосу, как показано на последнем рисунке. (Примечание: пунктирная линия и коричневая стрелка не нанесены на R, я добавил их в Paint для облегчения видимости и объяснения.) Итак, моей «неотложной» идеей было разделить интервал, соответствующий маленькому треугольнику (показан коричневым цветом). стрелка) на множество подинтервалов (скажем, 20-30) и добавьте одну фиолетовую полосу к каждому из подинтервалов таким образом, чтобы они заполняли область до красная линия целиком, по крайней мере заметно . Хотя это очень-очень не элегантный обходной путь.

Но это все еще не помогает мне со вторым вопросом, то есть как сделать прозрачной фиолетовую область под пунктирной линией;хотя я начинаю задаваться вопросом, возможно ли это вообще.

library(ggplot2)

equation <- function(x) {
  1 - 0.01 * x
}
inv_equation <- function(y) {
  (1-y)/0.01
}

x1 <- 0:44


dat <- data.frame(
  class = rep(c("top", "bottom"), each = length(x1)),
  type = c(rep("A", 6), rep("B", 39)),
  dat_x = rep(x1, 2),
  dat_y = c(c(rep(0.70, 6), rep(0.45, 39)), rep(0.05, length(x1))),
  dat_eq = rep(equation(x1), 2)
)

y2   <- rep(0.75, floor(inv_equation(0.75)-5))
dat2 <- data.frame(x=6:inv_equation(0.75), y=y2)

ggplot(dat, aes(x = dat_x, y = dat_y)) +
  geom_bar(data = dat2, aes(x=x, y=y), width = 1, fill = "purple", stat = "identity") +
  geom_col(aes(fill = class), width = 1) + 
  geom_line(data = cbind(dat["dat_x"], dat["dat_y"]), aes(x=rep(x1,2), y=rep(equation(x1), 2)), colour = "red", size = 1) +
  coord_cartesian(ylim=c(0,1))

enter image description here

1 Ответ

1 голос
/ 11 октября 2019

Хорошо, в конце концов оказалось, что это не так сложно, мне удалось решить это самостоятельно. Я использовал функцию geom_polygon() из ggplot2, эстетический параметр которой получает координаты x и y четырех вершин трапеции. Эти координаты могут быть вычислены автоматически из функции inv_equation().

Код выглядит следующим образом (мне не нужно было изменять какой-либо предыдущий код):

ggplot() + 
  geom_bar(data = dat[1:45,], aes(x=dat["dat_x"]$dat_x[1:45], 
                                  y=dat["dat_y"]$dat_y[1:45]+dat[46:90,]$dat_y), 
           width = 1, fill = "#F8766D", stat = "identity") +
  geom_bar(data = dat[1:45,], aes(x=dat["dat_x"]$dat_x[1:45], 
                                  y=dat["dat_y"]$dat_y[1:45]), 
           width = 1, fill = "#00BFC4", stat = "identity") + 
  geom_line(data = cbind(dat["dat_x"], dat["dat_y"]), 
            aes(x=rep(x1,2), y=rep(equation(x1), 2)), colour = "red", size = 1) +
  geom_polygon(aes(x=c(5.5, inv_equation(0.7), inv_equation(0.75), 5.5), 
                   y=c(0.7, 0.7, 0.75, 0.75)), fill = "purple") +
  coord_cartesian(ylim=c(0,1))

И результат: enter image description here

...