我想绘制几个正态分布并将每条曲线下的区域遮蔽到x = 6的右边和对称值的左边......
我已经定义了两个功能来轻松完成。
mifun <- function(x,mm,ss,alt) {
y <- alt+dnorm(x, mean = mm, sd = ss)
return(y)
}
mifun2 <- function(x,mm,ss,alt) {
y <- alt+dnorm(x, mean = mm, sd = ss)
y[x<6 & (2*mm-x)<6 ] <- NA
return(y)
}
ggplot(data.frame(x = c(-5, 11)), aes(x)) +
stat_function(fun = function(x) mifun(x,0,2,0), geom = "line") +
stat_function(fun = function(x) mifun2(x,0,2,0), geom = "area") +
stat_function(fun = function(x) mifun(x,2,2,-0.4), geom = "line") +
stat_function(fun = function(x) mifun2(x,2,2,-0.4), geom = "area") +
stat_function(fun = function(x) mifun(x,4,2,-0.8), geom = "line") +
stat_function(fun = function(x) mifun2(x,4,2,-0.8), geom = "area") +
stat_function(fun = function(x) mifun(x,6,2,-1.2), geom = "line") +
stat_function(fun = function(x) mifun2(x,6,2,-1.2), geom = "area") +theme_bw()
正如您所看到的,阴影出现在法线上方而不是下方。
答案 0 :(得分:1)
我认为上述评论是正确的:分面将成为可行的方法。不幸的是,facet_wrap
(和facet_grid
)与stat_function
的效果不佳,因为没有好的方法将faceting变量传递给stat_function
(无论如何我都能找到)
因此,您可能需要先生成密度曲线和区域以进行填充。请注意,geom_area
填补了点之间的空白,因此您需要mifun2
输出0
而不是NA
,其中应该没有填充:
mifun2 <- function(x,mm,ss,alt) {
y <- alt+dnorm(x, mean = mm, sd = ss)
y[x<6 & (2*mm-x)<6 ] <- 0
return(y)
}
然后,生成所需的网格化data.frame。这里我使用4个值(来自你的问题)和你想要绘制的范围内的1001个点:
normCurves <-
data.frame(x = rep(seq(-5, 11, length.out = 1001)
, times = 4)
, myMean = rep(c(0,2,4,6)
, each = 1001))
然后,使用您的两个函数生成密度和面积填充的可绘制列:
normCurves$density <-
mifun(normCurves$x, normCurves$myMean, 2, 0)
normCurves$toHighlight <-
mifun2(normCurves$x, normCurves$myMean, 2, 0)
然后直接绘制那些,使用facet_wrap
分隔各种方法:
ggplot(normCurves
, aes(x)) +
geom_line(aes(y = density)) +
geom_area(aes(y = toHighlight)) +
facet_wrap(~myMean, ncol = 1, labeller = label_both)
给出:
这种方法也适用于以不同的颜色绘制彼此之上的所有内容:
ggplot(normCurves
, aes(x
, col = factor(myMean)
, fill = factor(myMean)
, group = myMean)) +
geom_line(aes(y = density)) +
geom_area(aes(y = toHighlight)
, alpha = 0.2
, col = NA
, position = "identity")
给出
如果你想要突出显示在另一个方向上比6更极端的东西(为什么?),你只需要改变你的mifun2
定义:
mifun2 <- function(x,mm,ss,alt) {
y <- alt+dnorm(x, mean = mm, sd = ss)
# Make changes for small means
y[mm <= 6 & x<6 & (2*mm-x)<6 ] <- 0
# Make changes for large means
y[mm > 6 & x>6 & (2*mm-x)>6 ] <- 0
return(y)
}
然后,添加addtional意味着:
normCurves <-
data.frame(x = rep(seq(-6, 18, length.out = 1001)
, times = 7)
, myMean = rep(seq(0, 12, 2)
, each = 1001))
现在,如果你重新运行与上面相同的绘图代码,你会得到:
你现在也提到你想要制作动画,这是相对简单的:
toAnimate <-
ggplot(normCurves
, aes(x
, group = myMean
, frame = myMean)) +
geom_line(aes(y = density)) +
geom_area(aes(y = toHighlight)
, position = "identity") +
ggtitle("Mean = ")
gganimate::gg_animate(toAnimate)
给出