如何在ggplot2中绘制函数族 [英] How to plot a function family in ggplot2

查看:198
本文介绍了如何在ggplot2中绘制函数族的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要根据一组参数绘制一组变量函数,比如说一组依赖于均值和标准差的正态分布曲线。
我发现



我的问题是系列中的曲线数量可能是,因此我试图按照以下方式修改代码:

  aa<  - 列表(列表(0.2,0.1),列表(0.7,0.05),列表(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(color = 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(概率的正常函数曲线)+
scale_colour_brewer(palette =Accent)+
labs(color =Groups)
p9

结果几乎成功这三条曲线除了它不区分颜色和图例外,如下所示:



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

code>



快速编辑:我刚刚了解到我刚刚从@BrodieG那里学到的一个习惯用语,这在这里非常适用:您可以直接向 ggplot 调用添加一个geoms或stats列表,这可以让您为 lapply 甚至 Map 避免 Reduce 的卷积,它可以让你并行传递许多变量。结合@ JulioSergio的 aes _ 方法,您可以得到一个可读的代码很容易定制的体面情节:



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






减少



该结构可以很好地满足 Reduce ,其中 init 设置为最初的 ggplot 调用。可以通过索引一个调色板函数来添加颜色,它可以通过对象在这个点上的层数来获得:



x + stat_function(fun = dnorm,args = y,
color = scales :: brewer_pal('qual',' (x,c(0,1))),(b $ b aa,
init = ggplot(data.frame(x = c(0,1)), aes(x = x)))



这种方法的缺点是它不能制作出很好的图例,因为它是硬编码的颜色。




预先计算



绘图之前的计算,这使得绘图本身非常简单:



<$ c $ (列表(0.2,0.1),列表(0.7,0.05),列表(0.45,0.2))
$ b aa< - 列表(tidyverse)

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


I need to plot a family of functions variying according to a set of parameters, say, a family of normal distribution curves that depend on the mean and standard deviation. I found here, a code snipet that almost do the task:

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 

In this case, the code plots exactly two curves, as shown below:

My problem is that the number of curves in the family could be any, thus I tried to adapt the code as follows:

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

The result is almost successful in that it depicts the three curves, except that it does not distinguish them by colors nor in the legend,as it is shown below:

I guess the problem arises from the manner the function aes() manages its arguments. Do you have any idea on how to rewrite my code?

解决方案

Add a list to ggplot

A quick edit: I just learned an idiom I just learned from @BrodieG that's very applicable here: you can add a list of geoms or stats directly to a ggplot call, which allows you to avoid the convolutions of Reduce for lapply or even Map, which lets you pass as many variables in parallel as you like. Combined with @JulioSergio's aes_ approach, you get a decent plot with readable code that's easily customizable:

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

The structure lends itself reasonably well to Reduce with init set to the initial ggplot call. Colors can be added by indexing a palette function by the number of layers in the object at that point:

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

The disadvantage of this approach is that it does not make a nice legend, as it's hardcoding colors.


Precalculate

One way around this is to simply do the calculations before plotting, which makes the plotting itself very simple:

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

这篇关于如何在ggplot2中绘制函数族的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆