【问题标题】:Generating multiple geom_smooth lines of data samples生成多条 geom_smooth 数据样本线
【发布时间】:2018-02-16 22:14:30
【问题描述】:

尝试在此处构建一个新的 geom 函数,该函数将按组从数据集中抽取点样本,并通过各个子集拟合多个局部回归。这将生成多个局部回归线作为完整数据集的样本。最后产生类似这样的东西:

尽管我在下面构建的函数(使用 reprex)继续出错。任何帮助表示赞赏。谢谢!

library(ggplot2)
library(dplyr)

geom_mline <- function(mapping = NULL, data = NULL, stat = "mline",
                         position = "identity", show.legend = NA,
                         inherit.aes = TRUE, na.rm = TRUE,
                         SPAN = .9, N_size = 50, N_LOESS = 50, ...) {
  layer(
    geom = geomMline,
    mapping = mapping,
    data = data,
    stat = stat,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(SPAN=SPAN,
                  N_size=N_size,
                  N_LOESS=N_LOESS,
                  ...)
  )
}

geomMline <- ggproto("geomMline", GeomLine,
                       required_aes = c("x", "y"),
                       default_aes = aes(colour = "black", size = 0.5, linetype = 1, alpha = NA)
)

stat_mline <- function(mapping = NULL, data = NULL, geom = "line",
                         position = "identity", show.legend = NA, inherit.aes = TRUE,
                         SPAN = .9, N_size = 50, N_LOESS = 50, ...) {
  layer(
    stat = StatMline,
    data = data,
    mapping = mapping,
    geom = geom,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(SPAN=SPAN,
                  N_size=N_size,
                  N_LOESS=N_LOESS,
                  ...
    )
  )
}

StatMline <- ggproto("StatMline", Stat,

                       required_aes = c("x", "y"),

                       compute_group = function(self, data, scales, params,
                                                SPAN = .9, N_size = 50, N_LOESS = 50) {

                         tf <- tempfile(fileext=".png")
                         png(tf)
                         plot.new()
                         colnames(data) <- c("x", "variable", "y")
                         LOESS_DF <- data.frame(y = seq(min(data$x), 
                                                               max(data$x), 
                                                               length.out = 50))

                         for(i in 1:N_LOESS){
                           # sample N_size points
                           df_sample <- sample_n(data, N_size)
                           # fit a loess
                           xx <- df_sample$x
                           yy <- df_sample$y
                           tp_est <- loess(yy ~ xx , span = SPAN) 
                           # predict accross range of x using loess model
                           loess_vec <- data.frame(
                             predict(tp_est, newdata = 
                                       data.frame(xx = seq(min(data$x), max(data$x), length.out = 500))))
                           colnames(loess_vec) <- as.character(i)
                           # repeat x times
                           LOESS_DF <- cbind(LOESS_DF,loess_vec)
                           #str(LOESS_DF)
                         }

                         invisible(dev.off())
                         unlink(tf)
                         data.frame(reshape2::melt(LOESS_DF, id = "y"))




                       }
)

# dummy data
library(reshape2)


x  <- seq(1,1000,1)
y1 <- rnorm(n = 1000,mean = x*2^1.1, sd = 200)
y2 <- rnorm(n = 1000,mean = x*1, sd = 287.3)
y3 <- rnorm(n = 1000,mean = x*1.1, sd = 100.1)

data <- data.frame(x , y1, y2, y3)

data <- melt(data, id.vars = "x")
str(data)

ggplot(data,aes(x,value,group = variable, color = va

riable))+geom_point()

    ggplot(data = data, aes(x = x, y = value, group=variable, color = variable)) +
  #geom_point(color="black") +
  #geom_smooth(se=FALSE, linetype="dashed", size=0.5) +
  #stat_mline(SPAN = .2, N_size = 50, N_LOESS = 5)
  geom_mline(SPAN = .2, N_size = 50, N_LOESS = 5)

    #data <- subset(data, variable == "y2")

【问题讨论】:

  • 评论似乎在编辑后被删除。类似于:ggplot(data = data, aes(x = x, y = value, group=variable, color = variable)) + geom_point() + geom_smooth(se=FALSE) 确实让我很接近,但我想画多个基于子集的局部回归。
  • 当我意识到(假设我理解您的问题)您想从数据中抽取样本并通过每个样本绘制回归线时,我删除了我的原始评论。我添加了一个答案,希望能解决您的问题。

标签: r ggplot2 data-visualization ggproto


【解决方案1】:

您可以使用现有的geom_smooth geom 并使用lapply 从原始数据帧的多个随机样本中生成geom_smooth 调用。例如:

# Fake data
set.seed(2)
dat = data.frame(x = runif(100, 0, 10))
dat$y = 2*dat$x - 0.5*dat$x^2 - 5 + rnorm(100, 0, 5)

ggplot(dat, aes(x, y)) + 
  geom_point() +
  lapply(1:10, function(i) {
    geom_smooth(data=dat[sample(1:nrow(dat), 20), ], se=FALSE)
    })

或者,将其全部保存在tidyverse

library(tidyverse)

ggplot(dat, aes(x, y)) + 
  geom_point() +
  map(1:10, ~geom_smooth(data=dat[sample(1:nrow(dat), 20), ], se=FALSE))

这是一种在 ggplot 中绘制分位数的方法。我不确定是否可以让stat_quantile 绘制丝带。为此,您可能必须在 ggplot 之外计算分位数回归并添加 use geom_ribbon 来添加值。

ggplot(dat, aes(x, y)) + 
  geom_point() +
  geom_quantile(quantiles=c(0.1, 0.5, 0.9), formula=y ~ poly(x, 2), 
                aes(color=factor(..quantile..), size=factor(..quantile..))) +
  scale_color_manual(values=c("red","blue","red")) +
  scale_size_manual(values=c(1,2,1)) +
  labs(colour="Quantile") +
  guides(colour=guide_legend(reverse=TRUE), size=FALSE) +
  theme_classic()

【讨论】:

  • 这个现在非常好用。谢谢!您是否认为有一种简单的方法可以扩展它,然后在每个 x 值处绘制预测的分位数。即添加到答案中的图片之类的东西?
  • 上图绘制了预测值散布的大约 90% 的分位数。
  • 第二个图似乎是在绘制观察值的分位数?而不是绘制多元局部回归预测的分位数的值?
  • 我想我不确定您在寻找什么。第二个图的阴影区域代表什么?
  • 阴影区域是多元局部回归预测值的上下分位数(90%)。例如,如果拟合了 500 条线,则每个 x 值都有 500 个预测值,可以从中估计分位数。
猜你喜欢
  • 2013-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-01
  • 2019-03-09
  • 1970-01-01
相关资源
最近更新 更多