如何在ggplot2中绘制函数族 [英] How to plot a function family in 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
调用。可以通过索引一个调色板函数来添加颜色,它可以通过对象在这个点上的层数来获得:
color = scales :: brewer_pal('qual',' (x,c(0,1))),(b $ b aa,
init = ggplot(data.frame(x = c(0,1)), aes(x = x)))
这种方法的缺点是它不能制作出很好的图例,因为它是硬编码的颜色。
预先计算
绘图之前的计算,这使得绘图本身非常简单:
$ 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屋!