Затененная область под кривой плотности в ggplot2

Я составил график распределения и хочу заштриховать область>95 процентилей. Однако, когда я пытаюсь использовать различные методы, описанные здесь: теневая область ggplot2 под кривой плотности по группам не работает, так как длина моего набора данных отличается.

AGG[,1]=seq(1:1000)
AGG[,2]=rnorm(1000,mean=150,sd=10)
Z<-data.frame(AGG) 
library(ggplot2)
ggplot(Z,aes(x=Z[,2]))+stat_density(geom="line",colour="lightblue",size=1.1)+xlim(0,350)+ylim(0,0.05)+geom_vline(xintercept=quantile(Z[,2],prob=0.95),colour="red")+geom_text(aes(x=quantile(Z[,2],prob=0.95)),label="VaR 95%",y=0.0225, colour="red")
#I want to add a shaded area right of the VaR in this chart

2 ответа

Это тот случай, когда вспомогательные функции ggplot и встроенные сводки могут оказаться скорее хлопотными, чем полезными. В вашей ситуации, вероятно, лучше рассчитать сводную статистику напрямую, а затем построить ее. В приведенном ниже примере я использую density а также quantile с базы stats библиотека для вычисления того, что будет построено. Передача этого ggplot напрямую оказывается гораздо проще, чем попытка манипулировать функциями суммирования ggplot. Таким образом, затенение достигается с помощью geom_ribbon и предполагаемая эстетическая система ggplot; не нужно копаться в сюжете объекта.

rm(list = ls())
library(magrittr)
library(ggplot2)

y <- rnorm(1000, 150, 10)

cutoff <- quantile(y, probs = 0.95)

hist.y <- density(y, from = 100, to = 200) %$% 
  data.frame(x = x, y = y) %>% 
  mutate(area = x >= cutoff)

the.plot <- ggplot(data = hist.y, aes(x = x, ymin = 0, ymax = y, fill = area)) +
  geom_ribbon() +
  geom_line(aes(y = y)) +
  geom_vline(xintercept = cutoff, color = 'red') +
  annotate(geom = 'text', x = cutoff, y = 0.025, color = 'red', label = 'VaR 95%', hjust = -0.1)
print(the.plot)

Вот решение с использованием функции WVPlots::ShadedDensity, Я буду использовать эту функцию, потому что ее аргументы не требуют пояснений, и поэтому сюжет может быть создан очень легко. С другой стороны, настройка немного сложнее. Но однажды ты обдумал ggplot объект, вы увидите, что это не так таинственно.

library(WVPlots)

# create the data
set.seed(1)
V1 = seq(1:1000)
V2 = rnorm(1000, mean = 150, sd = 10)
Z <- data.frame(V1, V2)

Теперь вы можете создать свой сюжет.

threshold <- quantile(Z[, 2], prob = 0.95)[[1]]
p <- WVPlots::ShadedDensity(frame = Z, 
                            xvar = "V2",
                            threshold = threshold,
                            title = "Your title",
                            tail = "right")
p

Но так как вы хотите, чтобы цвет линии был светло-голубым и т.д., вам нужно манипулировать объектом p, В связи с этим см. Также этот и этот вопрос.

Предмет p содержит четыре слоя: geom_line, geom_ribbon, geom_vline а также geom_text, Вы найдете их здесь: p$layers,

Теперь вам нужно изменить их эстетическое отображение. За geom_line есть только один, colour

p$layers[[1]]$aes_params
$colour
[1] "darkgray"

Если вы хотите изменить цвет линии на светло-голубой, просто замените существующий цвет следующим образом

p$layers[[1]]$aes_params$colour <- "lightblue"

Как только вы поняли, как это сделать для одного layerостальное легко.

p$layers[[2]]$aes_params$fill <- "grey"     #geom_ribbon
p$layers[[3]]$aes_params$colour <- "red"    #geom_vline
p$layers[[4]]$aes_params$label <- "VaR 95%" #geom_text

p

И сюжет теперь выглядит так

Другие вопросы по тегам