【问题标题】:How to plot a function family in ggplot2如何在 ggplot2 中绘制函数族
【发布时间】:2017-04-19 22:45:31
【问题描述】:

我需要绘制一组根据一组参数变化的函数,例如一组取决于均值和标准差的正态分布曲线。 我找到了here,一个几乎可以完成任务的代码片段:

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 

在这种情况下,代码正好绘制了两条曲线,如下所示:

我的问题是家庭曲线的数量可以是任意的,因此我尝试将代码修改如下:

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

结果几乎是成功的,因为它描绘了三条曲线,除了它没有通过颜色和图例来区分它们,如下所示:

我猜问题出在函数 aes() 管理其参数的方式上。你知道如何重写我的代码吗?

【问题讨论】:

标签: r plot ggplot2


【解决方案1】:

将列表添加到ggplot

快速编辑:我刚刚了解到an idiom I just learned from @BrodieG 在这里非常适用:您可以将几何或统计数据列表直接添加到ggplot 调用中,这样您就可以避免Reducelapply 的卷积甚至Map,它允许您并行传递任意数量的变量。结合@JulioSergio 的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

该结构非常适合Reduceinit 设置为初始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)))

这种方法的缺点是它没有很好的图例,因为它是硬编码颜色。


预先计算

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

library(tidyverse)

aa <- list(list(0.2, 0.1), list(0.7, 0.05), list(0.45, 0.2))

aa %>% set_names(paste('Group', 1:3)) %>% 
    map_df(~dnorm(seq(0, 1, length = 100), .x[[1]], .x[[2]])) %>% 
    mutate(x = seq(0, 1, length = 100)) %>% 
    gather(Group, y, -x) %>% 
    ggplot(aes(x, y, color = Group)) + 
    geom_line()

【讨论】:

    【解决方案2】:

    reduce,用 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
    

    下图显示了结果:

    在这种情况下,优势在于生成的图像具有图例 使用适当的标签。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-02
      • 1970-01-01
      相关资源
      最近更新 更多