如何在ggplot2中绘制函数族

时间:2017-04-18 02:42:10

标签: r plot ggplot2

我需要根据一组参数绘制一系列函数,例如,一系列依赖于均值和标准差的正态分布曲线。 我找到了here,一个几乎完成任务的代码snipet:

p9 <- ggplot(data.frame(x = c(0, 1)), aes(x = x)) +
    stat_function(fun = dnorm, args = list(0.2, 0.1),
                  aes(colour = "Group 1")) +
    stat_function(fun = dnorm, args = list(0.7, 0.05),
                  aes(colour = "Group 2")) +
    scale_x_continuous(name = "Probability",
                          breaks = seq(0, 1, 0.2),
                          limits=c(0, 1)) +
    scale_y_continuous(name = "Frequency") +
    ggtitle("Normal function curves of probabilities") +
    scale_colour_brewer(palette="Accent") +
    labs(colour = "Groups")
p9 

在这种情况下,代码会精确绘制两条曲线,如下所示:

two curves

我的问题是系列中的曲线数量可以是任意,因此我尝试按如下方式调整代码:

aa <- list(list(0.2, 0.1), list(0.7, 0.05), list(0.45, 0.2))
p9 <- ggplot(data.frame(x = c(0, 1)), aes(x = x))
for (i in 1:3) {
    p9 <- p9 + stat_function(fun = dnorm, args = aa[[i]],
                         aes(colour = paste("Group", i))
}
p9 <- p9 + 
  scale_x_continuous(name = "Probability",
                   breaks = seq(0, 1, 0.2),
                   limits=c(0, 1)) +
  scale_y_continuous(name = "Frequency") +
  ggtitle("Normal function curves of probabilities") +
  scale_colour_brewer(palette="Accent") +
  labs(colour = "Groups")
p9

结果几乎是成功的,因为它描绘了三条曲线,除了它不能通过颜色或传奇区分它们,如下所示:

any number of curves

我猜问题来自函数aes()管理其参数的方式。您对如何重写我的代码有任何想法吗?

2 个答案:

答案 0 :(得分:4)

将列表添加到ggplot

快速修改:我刚学会了an idiom I just learned from @BrodieG这里非常适用:你可以直接在ggplot来电添加一个geoms或stats列表,这样你就可以避免卷积Reducelapply的{​​{1}},可让您根据需要并行传递尽可能多的变量。结合@ JulioSergio的Map方法,您可以获得一个可读的代码,可以轻松定制:

aes_

ggplot(data.frame(x = 0:1), aes(x)) + Map(function(params, name){stat_function(mapping = aes_(color = name), fun = dnorm, args = params)}, params = aa, name = paste('Group', seq_along(aa)))

结构非常适合Reduce Reduce设置为初始init调用。可以通过将调色板功能按此时对象中的层数索引来添加颜色:

ggplot

这种方法的缺点在于它没有成为一个很好的传奇,因为它的硬编码颜色。

预先计算

解决这个问题的一种方法是在绘图之前简单地进行计算,这使得绘图本身非常简单:

Reduce(function(x, y){
    x + stat_function(fun = dnorm, args = y, 
                      colour = scales::brewer_pal('qual', 'Set1')(length(aa))[length(x$layers) + 1])}, 
    aa, 
    init = ggplot(data.frame(x = c(0, 1)), aes(x = x)))

答案 1 :(得分:2)

减少,使用aes_()添加图例

以下答案使用 aes _()函数代替 aes()来执行美学映射,因为我了解到,它更适合编程。我以alistaire给出的答案作为基础。

library(ggplot2)
aa <- list(list(0.2, 0.1), list(0.7, 0.05), list(0.45, 0.2))
p9 <- Reduce(function(x, y){
  x + stat_function(fun = dnorm, args = y, 
                  aes_(colour = paste("Group", length(x$layers)+1)))}, 
  aa, 
  init = ggplot(data.frame(x = c(0, 1)), aes(x = x)))
p9 <- p9 + 
  scale_x_continuous(name = "Probability",
                   breaks = seq(0, 1, 0.2),
                   limits=c(0, 1)) +
  scale_y_continuous(name = "Frequency") +
  ggtitle("Normal function curves of probabilities") +
  scale_colour_brewer(palette="Accent") +
  labs(colour = "Groups")
p9

下图显示了结果:

Result

在这种情况下,优点是结果图像具有图例 用合适的标签。