使用stat_function()在R中的ggplot中绘制大量自定义函数

时间:2013-11-07 21:07:13

标签: r ggplot2

基本问题是我想弄清楚如何在ggplot的同一图中添加大量(1000)自定义函数,使用不同的函数系数值。我已经看到了关于如何添加两个或三个函数但不是1000的其他问题,以及关于添加不同函数形式的问题,但不是具有多个参数值的相同形式......

目标是让stat_function使用存储在数据框中的参数值绘制线条,但没有x的实际数据。

[这里的总体目标是显示来自小数据集的非线性回归的模型参数的大的不确定性,这转化为与该数据的预测相关的不确定性(我试图说服其他人是一个坏主意)。我经常通过绘制由模型参数中的不确定性构建的许多线来实现这一点(安德鲁·格尔曼的多级回归教科书)。]

例如,这是基础R图形中的图。

#The data
p.gap <- c(50,45,57,43,32,30,14,36,51)
p.ag <- c(43,24,52,46,28,17,7,18,29)
data <- as.data.frame(cbind(p.ag, p.gap))

#The model (using non-linear least squares regression):
fit.1.nls <- nls(formula=p.gap~beta1*p.ag^(beta2), start=list(beta1=5.065, beta2=0.6168))
summary(fit.1.nls)

#From the summary, I find the means and s.e's the two parameters, and develop their distributions:
beta1 <- rnorm(1000, 7.8945, 3.5689)
beta2 <- rnorm(1000, 0.4894, 0.1282)
coefs <- as.data.frame(cbind(beta1,beta2))

#This is the plot I want (using curve() and base R graphics):
plot(data$p.ag, data$p.gap, xlab="% agricultural land use",
     ylab="% of riparian buffer gap", xlim=c(0,130), ylim=c(0,130), pch=20, type="n")
for (i in 1:1000){curve(coefs[i,1]*x^(coefs[i,2]), add=T, col="grey")}
curve(coef(fit.1.nls)[[1]]*x^(coef(fit.1.nls)[[2]]), add=T, col="red")
points(data$p.ag, data$p.gap, pch=20)

我可以用ggplot中的数据绘制平均模型函数:

fit.mean <- function(x){7.8945*x^(0.4894)}
ggplot(data, aes(x=p.ag, y=p.gap)) +
  scale_x_continuous(limits=c(0,100), "% ag land use") +
  scale_y_continuous(limits=c(0,100), "% riparian buffer gap") +
  stat_function(fun=fit.mean, color="red") +
  geom_point()

但我没有做任何事情在ggplot中绘制多行。我似乎没有找到任何帮助从ggplot网站或本网站上的函数绘制参数值,这通常都非常有用。这是否违反了足够的策划理论,没有人敢这样做?

感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:12)

可以将多个geoms或stats(甚至是绘图的其他元素)收集到矢量或列表中,并将该矢量/列表添加到绘图中。使用此功能,plyr包可用于制作stat_function的列表,每coefs行一个

library("plyr")
coeflines <-
alply(as.matrix(coefs), 1, function(coef) {
  stat_function(fun=function(x){coef[1]*x^coef[2]}, colour="grey")
})

然后将其添加到情节

ggplot(data, aes(x=p.ag, y=p.gap)) +
  scale_x_continuous(limits=c(0,100), "% ag land use") +
  scale_y_continuous(limits=c(0,100), "% riparian buffer gap") +
  coeflines +
  stat_function(fun=fit.mean, color="red") +
  geom_point()

enter image description here

几点说明:

  • 这很慢。我的电脑花了几分钟画画。 ggplot的设计效率不高,只能处理大约1000层。
  • 这只是添加1000行的地址。 Per @ Roland的评论,我不知道这是否代表你想要/期望它的统计数据。

答案 1 :(得分:1)

您可以创建一个新的stat_functions /修改stat_function以接受fun这样的美感:

# based on code from hadley and others
# found on https://github.com/tidyverse/ggplot2/blob/master/R/stat-function.r
library(rlang)
StatFunctions <- ggproto("StatFunctions", Stat,
                         default_aes = aes(y = stat(y)),
                         required_aes = "fun",

                         compute_group = function(data, scales, xlim = NULL, n = 101, args = list()) {
                           range <- xlim %||% scales$x$dimension()
                           xseq <- seq(range[1], range[2], length.out = n)

                           if (scales$x$is_discrete()) {
                             x_trans <- xseq
                           } else {
                             # For continuous scales, need to back transform from transformed range
                             # to original values
                             x_trans <- scales$x$trans$inverse(xseq)
                           }
                          do.call(rbind,
                                  lapply(data$fun, function(fun)
                                    data.frame(
                                      x = xseq,
                                      y =  do.call(fun, c(list(quote(x_trans)), args))))
                          )
                          }
)

stat_functions <- function(mapping = NULL, data = NULL,
                           geom = "path", position = "identity",
                           ...,
                           xlim = NULL,
                           n = 101,
                           args = list(),
                           na.rm = FALSE,
                           show.legend = NA,
                           inherit.aes = TRUE) {
  layer(
    data = data,
    mapping = mapping,
    stat = StatFunctions,
    geom = geom,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      n = n,
      args = args,
      na.rm = na.rm,
      xlim = xlim,
      ...
    )
  )
}

然后像这样使用它:

df <- data.frame(fun=1:3)
df$fun = c(function(x) x, function(x) x^2, function(x) x^3)
ggplot(df,aes(fun=fun, color=as.character(fun)))+
  stat_functions() +
  xlim(c(-5,5))

要获取此信息: enter image description here