如何在平滑器中为 "missing" 值创建间隙(R,ggplot)

How create gaps in smoother for "missing" values (R, ggplot)

如果我有这样的数据集

set.seed(100)
data <- data.frame("x" = c(1, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 5, 5),
                   "y" = rnorm(13),
                   "factor" = c("a","b","c","a","b", "c", "c", "a",
                                "b", "c", "a", "b","c"))

看起来像这样

   x           y factor
1  1 -0.50219235      a
2  1  0.13153117      b
3  1 -0.07891709      c
4  2  0.88678481      a
5  2  0.11697127      b
6  2  0.31863009      c
7  3 -0.58179068      c
8  4  0.71453271      a
9  4 -0.82525943      b
10 4 -0.35986213      c
11 5  0.08988614      a
12 5  0.09627446      b
13 5 -0.20163395      c

我想用一个单独的更平滑的每个因子 (a,b,c) 来绘制它

library(ggplot2)
ggplot(data = data, aes(x = x, y = y, col = factor)) + 
  geom_smooth(aes(group = factor))

但是由于 x = 3 没有 "a" 和 "b" 的值,所以我希望 "a" 和 "b" 的平滑器可以休息一下对于 x = 3。实现该目标的最佳策略是什么?

我会创建 xfactor 组合的扩展,然后对这些组合和数据进行类似数据库的连接。例如,首先我用 xfactor

的唯一值组合形成一个新的数据框 df
df <- expand.grid(sapply(data[, c("x", "factor")], unique))

> df
   x factor
1  1      a
2  2      a
3  3      a
4  4      a
5  5      a
6  1      b
7  2      b
8  3      b
9  4      b
10 5      b
11 1      c
12 2      c
13 3      c
14 4      c
15 5      c

然后我们可以简单地对 df 和您的 data 执行连接操作,要求我们 return 左侧的所有行(x 参数,因此 df),并从右侧 (data) 包含 y 的相应值。如果没有相应的右侧(在 data 中,我们将得到一个 NA.

newdf <- merge(df, data, all.x = TRUE)

> newdf
   x factor           y
1  1      a -0.50219235
2  1      b  0.13153117
3  1      c -0.07891709
4  2      a  0.88678481
5  2      b  0.11697127
6  2      c  0.31863009
7  3      a          NA
8  3      b          NA
9  3      c -0.58179068
10 4      a  0.71453271
11 4      b -0.82525943
12 4      c -0.35986213
13 5      a  0.08988614
14 5      b  0.09627446
15 5      c -0.20163395

现在我们可以手动拟合和预测黄土模型,但这有点乏味 - 通过 mgcv:gam()

可以获得更简单的选项
loessFun <- function(XX, span = 0.85) {
  fit <- loess(y ~ x, data = XX, na.action = na.exclude, span = span)
  predict(fit)
}

现在将数据拆分 factor 并应用 loessFun() 包装器

fits <- lapply(split(newdf, newdf$factor), loessFun)
newdf <- transform(newdf, fitted = unsplit(fits, factor))

> head(newdf)
  x factor           y      fitted
1 1      a -0.50219235 -0.50219235
2 1      b  0.13153117  0.13153117
3 1      c -0.07891709 -0.07891709
4 2      a  0.88678481  0.88678481
5 2      b  0.11697127  0.11697127
6 2      c  0.31863009  0.31863009

然后我们可以使用新数据框进行绘图

ggplot(newdf, aes(x = x, y = y, col = factor)) + 
  geom_line(aes(group = factor))

给出:

它看起来有点古怪,因为您提供的样本数据的分辨率非常低,而且我使用的这种方法仅预测观察到的数据,保留 NAs。 geom_smooth() 实际上是分别为每个组预测 x 的范围,因此在用于绘制 geom 层的数据中没有丢失 xs。

除非您能解释我们应该在 x = 3 的哪个区域内添加中断(NA),否则这可能是您所能做的最好的事情。或者,我们可以根据模型预测整个区域,然后将任何 2.5 < x < 3.5 设置回 NA。如果那是你想要的,请添加评论,我将通过一个例子来扩展我的答案如果你可以说明我们如何设想差距。