如何为几个正态分布下方的区域着色?

时间:2015-06-21 21:19:35

标签: r normal-distribution standard-deviation

经过几次尝试,我终于可以获得一个具有几个正态分布的独特图形。在这些分布中,1sd也被绘制为垂直矩形。我使用的代码就是这个:

x1<-50:200
a1<-dnorm(x1,134,20)
b1<-dnorm(x1,130,14)
c1<-dnorm(x1,132,12)
d1<-dnorm(x1,105,10)

scale<-range(pretty(range(a1,b1,c1,d1)))

remap<-function(x, to, from=range(x)) {
    (x-from[1]) / (from[2]-from[1]) * (to[2]-to[1]) + to[1] 
}

plot(NA, NA, xaxt="n", yaxt="n", type="n", xlim=scale, ylim=scale, xlab="Variable X", ylab="")
rect(remap(134-20, scale, range(x1)), scale[1],
     remap(134+20, scale, range(x1)), scale[2], col="#ff606025")
rect(remap(130-14, scale, range(x1)), scale[1],
     remap(130+14, scale, range(x1)), scale[2], col="#005ccd40")
rect(remap(132-12, scale, range(x1)), scale[1],
     remap(132+12, scale, range(x1)), scale[2], col="#005ccd40")
rect(remap(105-10, scale, range(x1)), scale[1],
     remap(105+10, scale, range(x1)), scale[2], col="#005ccd40")
#R1429
rect(remap(183, scale, range(x1)), scale[1],
     remap(183, scale, range(x1)), scale[2], col="darkblue", lwd=3,lty=3)

lines(remap(x1,scale), a1, col="#ff6060", lwd=3)
lines(remap(x1,scale), b1, col="#005ccd", lwd=3, lty=3)
lines(remap(x1,scale), c1, col="#005ccd", lwd=3)
lines(remap(x1,scale), d1, col="#005ccd", lwd=3,lty=3)

axis(2);
axis(1, at=remap(pretty(x1), scale), pretty(x1))

运行代码后我得到了下一个数字: enter image description here

但我的问题是:我如何只为每个正态分布下面的区域着色,而不是做垂直矩形呢?

解释会容易得多。

提前致谢!

4 个答案:

答案 0 :(得分:4)

这是使用ggvis的另一个版本:

library(dplyr)
library(ggvis)

## -- data generation copied from @NickK -- ##
data.frame(group = letters[1:4],
           m = c(130, 134, 132, 105),
           s = c(20, 14, 12, 10)) %>%
  group_by(group) %>%
  do(data_frame(group = .$group,
                x = 50:200,
                y = dnorm(x, .$m, .$s),
                withinSd = abs(x - .$m) <= .$s)) %>%
## ---------------------------------------- ##
  mutate(dash = ifelse(grepl("a|d", group), 5, 0),
         color = ifelse(grepl("a|c|d", group), "blue", "red"))  %>%
  ggvis() %>%
  layer_paths(~x, ~y, stroke := ~color, strokeDash := ~dash) %>%
  filter(withinSd) %>%
  layer_ribbons(~x, ~y, y2 = ~y-y, fill := ~color, fillOpacity := 0.2) %>%
  hide_legend("fill") %>%
  add_axis("y", title_offset = 50)

enter image description here

答案 1 :(得分:3)

您可以使用polygon填写曲线。

## Some distributions
x1 <- 50:200
means <- c(134, 130, 132, 105)
sds <- c(20, 14, 12, 10)
dists <- lapply(seq_along(means), function(i) dnorm(x1, means[i], sds[i]))

## Some colors
cols <- colorRampPalette(c("red", "blue"))(length(dists))

## Blank plot
plot(c(x1[1], x1[length(x1)]), c(min(unlist(dists)), max(unlist(dists))), 
     type="n", xlab="X", ylab="Density")

## Add polygons
for (i in seq_along(dists))
    polygon(c(x1, rev(x1)), 
            c(numeric(length(x1)), rev(dists[[i]])), 
            col=cols[i],
            density=40)

enter image description here

编辑:对于1sd内的多边形

xs <- sapply(seq_along(dists), function(i)  # get supports on x1
    do.call(`:`, as.list(which(x1 %in% (means[i] + c(-1,1)*sds[i])))))

plot(range(x1), range(unlist(dists)), type="n", xlab="X", ylab="Density")
for (i in seq_along(dists)) {
    x <- x1[xs[[i]]]
    polygon(c(x, rev(x)), 
            c(numeric(length(x)), rev(dists[[i]][xs[[i]]])), 
            col=cols[i],
            density=40)
    points(x1, dists[[i]], type="l", lty=2, col=cols[i])
}

enter image description here

答案 2 :(得分:3)

这是使用Hadley Wickham的一些软件包来实现它的方法:

library("dplyr")
library("ggplot2")
library("tidyr")
data.frame(x = 50:200) %>%
  mutate(a = dnorm(x,134,20),
         b = dnorm(x,130,14),
         c = dnorm(x,132,12),
         d = dnorm(x,105,10)) %>%
  gather(group, y, -x) %>%
  ggplot(aes(x, y, fill = group)) %>%
  + geom_area(alpha = 0.3, position = "identity") %>%
  + geom_line() %>%
  print

output with 4 normal distributions

这是一个仅在1 SD内填充的版本:

data.frame(group = letters[1:4],
  m = c(130, 134, 132, 105),
  s = c(20, 14, 12, 10)
) %>%
  group_by(group) %>%
  do(data_frame(group = .$group,
    x = 50:200,
    y = dnorm(x, .$m, .$s),
    withinSd = abs(x - .$m) <= .$s)
  ) %>% {
    ggplot(., aes(x = x, y = y, colour = group)) +
      geom_line() +
      geom_area(aes(fill = group), filter(., withinSd),
        position = "identity", alpha = 0.3) +
      guides(colour = "none")
    }

Graph with 1 SD

如果您希望图表的高度相同,则可以添加一些额外的dplyr魔法:

data.frame(group = letters[1:4],
           m = c(130, 134, 132, 105),
           s = c(20, 14, 12, 10)
) %>%
  group_by(group) %>%
  do(data_frame(group = .$group,
                x = 50:200,
                y = dnorm(x, .$m, .$s),
                withinSd = abs(x - .$m) <= .$s)
  ) %>% 
  group_by(group) %>%
  mutate(y = y / max(y)) %>%
  {
    ggplot(., aes(x = x, y = y, colour = group)) +
      geom_line() +
      geom_area(aes(fill = group), filter(., withinSd),
                position = "identity", alpha = 0.3) +
      guides(colour = "none")
  }

enter image description here

答案 3 :(得分:3)

这是使用基础R的另一个版本。这个版本使用var apiRoot = 'https://api.github.com'; var myUser = YOUR_USER_HERE; var myRepo = YOUR_REPO_HERE; var request = new XMLHttpRequest(); request.open('GET', apiRoot + '/repos/' + myUser + '/' + myRepo + '/readme'); request.setRequestHeader('Accept','application/vnd.github.v3.html'); /* add event listeners... */ request.onreadystatechange = function() { if (request.readyState === 4 && request.status === 200) { document.body.innerHTML = request.response; } }; request.send();中的type='h'选项绘制了很多垂直线,这么多,它最终会遮蔽区域。请注意,这需要增加lines()中的采样点数量(尝试将x1更改回x1以查看会发生什么情况。)

50:200

这是输出:

a busy cat