R:Shadindg在ggplot的几个法线下

时间:2017-01-17 15:52:36

标签: r ggplot2

我想绘制几个正态分布并将每条曲线下的区域遮蔽到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()

这是没有阴影的图片: enter image description here

这是带阴影的图片,它不能按预期工作: enter image description here

如果我只绘制一个正常情节,我会得到这个 enter image description here

正如您所看到的,阴影出现在法线上方而不是下方。

PD:Mark的照片 enter image description here 如您所见,第一个图在右侧阴影限制上对齐,后者在左侧对齐。

1 个答案:

答案 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)

给出:

enter image description here

这种方法也适用于以不同的颜色绘制彼此之上的所有内容:

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")

给出

enter image description here

如果你想要突出显示在另一个方向上比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))

现在,如果你重新运行与上面相同的绘图代码,你会得到:

enter image description here

你现在也提到你想要制作动画,这是相对简单的:

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)

给出

enter image description here