[英]How to plot a function family in ggplot2
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:
我在这里找到了一个几乎完成任务的代码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
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. 我想问题来自函数aes()管理其参数的方式。 Do you have any idea on how to rewrite my code?
你对如何重写我的代码有任何想法吗?
ggplot
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. 快速编辑:我刚刚从@BrodieG那里学到了一个非常适用的成语 :你可以直接在
ggplot
调用中添加一个geoms或stats列表,这样你就可以避免使用Reduce
来解决lapply
甚至Map
,它允许您根据需要并行传递尽可能多的变量。 Combined with @JulioSergio's aes_
approach, you get a decent plot with readable code that's easily customizable: 结合@ 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
The structure lends itself reasonably well to Reduce
with init
set to the initial ggplot
call. 该结构使其本身相当不错,以
Reduce
与init
设置为初始ggplot
电话。 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. 这种方法的缺点是它没有成为一个很好的传说,因为它是硬编码的颜色。
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()
The following answer uses aes_() function instead of aes() to perform the aesthetics mapping, since, I learnt, it is more suitable for programming. 下面的答案使用aes_()函数而不是aes()来执行美学映射,因为,我了解到,它更适合编程。 I took as a basis the answer given by alistaire .
我把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
The figure below shows the result: 下图显示了结果:
The advantage, in this case, is that the resulting image has a legend with the proper labels. 在这种情况下,优点是结果图像具有带有适当标签的图例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.