【问题标题】:ggplot2: Getting a color legend to appear using stat_function() in a for loopggplot2:在 for 循环中使用 stat_function() 获取颜色图例
【发布时间】:2015-06-04 22:33:57
【问题描述】:

我正在尝试使用 stat_function() 将一些分布添加到绘图中。我可以使用以下代码成功地做到这一点:

library("ggplot2")
library("dplyr")

gg_color_hue <- function(n) {
  hues = seq(15, 375, length=n+1)
  hcl(h=hues, l=65, c=100)[1:n]
}

plotMixMdlComps <- function(x, mu, sigma, lam) {
  lam * dnorm(x, mu, sigma )
}

clusterDf <- data.frame(cluster = c(6,5,4,8,0,7,3),
                        mu = c(0.73908779, 0.43233777, 0.28041006, 0.35627709,
                               0.09330585, 0.18250758, 0.56998734),
                        sigma = c(0.06472281, 0.03218096, 0.02779751,
                                  0.02208605, 0.02716692, 0.01890661,
                                  0.02995616),
                        lambda = c(0.042749908, 0.254485536, 0.205602343,
                                   0.404705236, 0.061058220, 0.024166972,
                                   0.007231783))

cols <- nrow(clusterDf) %>%
  gg_color_hue()

inDf <- data.frame(x = c(0,1))

p <- ggplot(inDf, aes(x)) +
  xlim(0,1) +
  ylim(0,10)

for (i in 1:nrow(clusterDf)) {
  p <- p + stat_function(geom = "line", fun = plotMixMdlComps,
                         arg = list(clusterDf[i, "mu"],
                                    clusterDf[i, "sigma"],
                                    clusterDf[i, "lambda"]),
                         lwd = 1.5, colour = cols[i])
}

p

这会生成一个像这样的图形:

但我想有一个传奇出现。在线阅读后,看来我可以像这样将颜色参数包装在 aes() 中:

p <- ggplot(inDf, aes(x)) +
  xlim(0,1) +
  ylim(0,10)

for (i in 1:nrow(clusterDf)) {
  p <- p + stat_function(geom = "line", fun = plotMixMdlComps,
                         arg = list(clusterDf[i, "mu"],
                                    clusterDf[i, "sigma"],
                                    clusterDf[i, "lambda"]),
                         lwd = 1.5, aes(colour = cols[i]))
}
p

但这最终会产生这样的情节,

我认为这与 NSE 有关(我仍然无法理解它),它只在调用时“解析”cols[i]。因此,每个 stat_function 最终都会解析为具有相同的 cols[i],应该是 cols[7]。有没有办法让 ggplot 立即“解决”这个问题,而不是等待 p 被调用?

谢谢,

【问题讨论】:

  • ggplot2 旨在处理长格式数据。重塑您的数据,以便有一列“变量”(具有值“mu”、“sigma”和“lambda”)和一列具有相应值的“值”。 (在您的示例中,它应该有 21 行。)然后将“变量”列映射到“颜色”美学,图例将自动出现。
  • @krlmlr 不确定如何使用 stat_function() 进行这项工作? plotMixMdlComps() 函数从 clusterDf 的每一行获取值来生成分布。如果我融化它,我如何 stat_function 检索每个集群所需的值?
  • 抱歉,您的问题只看了一半。但总体思路保持不变:使用您的 plot... 函数和一些 x 值(不要太少,不要太多)创建一个长格式的数据框,其中包含您想要的线上每个点的一行地块。 (现在包含length(x) * 7 行。)然后,对整个数据框仅使用aes(x=x, y=y, color=cluster),并且不要使用循环来构建绘图。

标签: r ggplot2


【解决方案1】:

stat_function 的帮助中有一个示例,用于在同一个图中显示两个函数。它还添加了两次stat_function 并指定了显式颜色并且不会生成自动图例:

f <- ggplot(data.frame(x = c(0, 10)), aes(x))
f + stat_function(fun = sin, colour = "red") +
  stat_function(fun = cos, colour = "blue")

因此,我怀疑用图例绘制几个函数不在stat_function 的范围内。

按照 krlmlr 的说明,您可以创建如下数据集:

x <- seq(0,1,0.01)
names(clusterDf)[4]<-"lam"
fun_data <- lapply(1:nrow(clusterDf),function(i) {
               args <- clusterDf[i,-1]
               data.frame(cluster=clusterDf$cluster[i],
                          x=x,
                          y=do.call(plotMixMdlComps,c(list(x=x),args))
               )
}) %>% bind_rows

现在可以使用 ggplot 直接绘制:

ggplot(fun_data,aes(x=x,y=y,colour=as.factor(cluster))) + geom_line(lwd=1.5)

这让 ggplot 为你挑选颜色。如果您想使用您指定的颜色(在您的情况下,这些颜色与 ggplot 选择的颜色相同),您可以将 scale_colour_manual(values=cols) 添加到绘图中。

编辑:

或者,您也可以使用来自plyr 包的mdply 创建绘图数据:

library(plyr)
x <- seq(0,1,0.01)
names(clusterDf)[4]<-"lam"
fun_data <- mdply(clusterDf,function(cluster,mu,sigma,lam) {
    data.frame(cluster=cluster,
               x=x,
               y=plotMixMdlComps(x,mu,sigma,lam)
    )
}) %>% bind_rows

【讨论】:

  • 抱歉回复晚了。非常感谢您的建议和代码。它解决了我的问题。
【解决方案2】:

距离最初的帖子已经很久了,ggplot2 发生了很大变化。现在也可以通过在aes() 中使用经过整理评估的准引用或使用aes_() 以编程方式将美学映射应用于stat_functionSee release note of ggplot2 3.0.0.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多