如何在ggplot2中绘制函数族

5

我需要绘制一组函数,这些函数根据一组参数变化,例如依赖于均值和标准差的正态分布曲线。

我在这里找到了一个几乎可以完成任务的代码片段:

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()管理其参数的方式上。你有没有想过如何重写我的代码?


https://dev59.com/voTba4cB1Zd3GeqP5F-5#26434007 - baptiste
我的图表没有显示出来。 - Zafar
2个回答

5

ggplot中添加列表

快速编辑:我刚学到一个成语(来自@BrodieG),非常适用于这里:您可以直接将几何或统计列表添加到ggplot调用中,这样可以避免使用Reduce进行lapply甚至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

该结构相对于 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)))

这种方法的缺点是它无法生成漂亮的图例,因为颜色是硬编码的。

预计算

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

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


3

使用aes_()来添加图例的Reduce函数

下面的答案使用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

在这种情况下的优点是,生成的图像具有正确标签的图例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接