在 ggplot2 中使用 geom_stat / geom_smooth 时查找高于和低于置信区间的点
Find points over and under the confidence interval when using geom_stat / geom_smooth in ggplot2
我有一个散点图,我想知道如何找到置信区间线上方和下方的基因?
编辑: 可重现示例:
library(ggplot2)
#dummy data
df <- mtcars[,c("mpg","cyl")]
#plot
ggplot(df,aes(mpg,cyl)) +
geom_point() +
geom_smooth()
我不得不深入研究 github
存储库,但我终于明白了。为此,您需要了解 stat_smooth
的工作原理。在这种特定情况下,调用 loess
函数来进行平滑处理(可以使用与以下相同的过程构造不同的平滑函数):
因此,在这种情况下使用 loess
我们会做:
#data
df <- mtcars[,c("mpg","cyl"), with=FALSE]
#run loess model
cars.lo <- loess(cyl ~ mpg, df)
然后我不得不阅读 this 以了解 stat_smooth
内部是如何做出预测的。显然 hadley 在我们的案例中使用 predictdf
函数(未导出到命名空间)如下:
predictdf.loess <- function(model, xseq, se, level) {
pred <- stats::predict(model, newdata = data.frame(x = xseq), se = se)
if (se) {
y = pred$fit
ci <- pred$se.fit * stats::qt(level / 2 + .5, pred$df)
ymin = y - ci
ymax = y + ci
data.frame(x = xseq, y, ymin, ymax, se = pred$se.fit)
} else {
data.frame(x = xseq, y = as.vector(pred))
}
}
阅读以上内容后,我可以使用以下方法创建自己的 data.frame 预测:
#get the predictions i.e. the fit and se.fit vectors
pred <- predict(cars.lo, se=TRUE)
#create a data.frame from those
df2 <- data.frame(mpg=df$mpg, fit=pred$fit, se.fit=pred$se.fit * qt(0.95 / 2 + .5, pred$df))
查看 predictdf.loess
,我们可以看到置信区间的上限创建为 pred$fit + pred$se.fit * qt(0.95 / 2 + .5, pred$df)
,下限创建为 pred$fit - pred$se.fit * qt(0.95 / 2 + .5, pred$df)
。
使用这些我们可以为超出或低于这些边界的点创建一个标志:
#make the flag
outerpoints <- +(df$cyl > df2$fit + df2$se.fit | df$cyl < df2$fit - df2$se.fit)
#add flag to original data frame
df$outer <- outerpoints
df$outer
列可能是 OP 正在寻找的内容(如果它在边界之外则取值 1,否则取值 0)但为了它我将其绘制在下面。
注意上面的+
函数在这里只用于将逻辑标志转换为数字。
现在如果我们这样画:
ggplot(df,aes(mpg,cyl)) +
geom_point(aes(colour=factor(outer))) +
geom_smooth()
我们实际上可以看到置信区间内外的点。
输出:
P.S。对于任何对上下边界感兴趣的人,它们是这样创建的(推测:虽然阴影区域可能是用 geom_ribbon 或类似的东西创建的 - 这使它们更圆更漂亮):
#upper boundary
ggplot(df,aes(mpg,cyl)) +
geom_point(aes(colour=factor(outer))) +
geom_smooth() +
geom_line(data=df2, aes(mpg , fit + se.fit , group=1), colour='red')
#lower boundary
ggplot(df,aes(mpg,cyl)) +
geom_point(aes(colour=factor(outer))) +
geom_smooth() +
geom_line(data=df2, aes(mpg , fit - se.fit , group=1), colour='red')
此解决方案利用了 ggplot2 为您所做的辛勤工作:
library(sp)
# we have to build the plot first so ggplot can do the calculations
ggplot(df,aes(mpg,cyl)) +
geom_point() +
geom_smooth() -> gg
# do the calculations
gb <- ggplot_build(gg)
# get the CI data
p <- gb$data[[2]]
# make a polygon out of it
poly <- data.frame(
x=c(p$x[1], p$x, p$x[length(p$x)], rev(p$x)),
y=c(p$ymax[1], p$ymin, p$ymax[length(p$x)], rev(p$ymax))
)
# test for original values in said polygon and add that to orig data
# so we can color by it
df$in_ci <- point.in.polygon(df$mpg, df$cyl, poly$x, poly$y)
# re-do the plot with the new data
ggplot(df,aes(mpg,cyl)) +
geom_point(aes(color=factor(in_ci))) +
geom_smooth()
它需要一些调整(即最后一点获得 2
值)但我的时间有限。请注意 point.in.polygon
return 值为:
0
: 点完全在 pol 之外
1
: 点严格在 pol 内部
2
: 点位于 pol 边的相对内部
3
: point是pol 的一个顶点
所以无论值是否为 0
,只需将代码更改为 TRUE
/FALSE
应该很容易。
使用 ggplot_build
就像@hrbrmstr 的不错的解决方案一样,您实际上可以通过简单地将一系列 x 值传递给 geom_smooth
来指定应该计算误差范围的位置,并使其等于你的点的 x 值。然后,您只需查看 y 值是否在范围内。
library(ggplot2)
## dummy data
df <- mtcars[,c("mpg","cyl")]
ggplot(df, aes(mpg, cyl)) +
geom_smooth(params=list(xseq=df$mpg)) -> gg
## Find the points within bounds
bounds <- ggplot_build(gg)[[1]][[1]]
df$inside <- with(df, bounds$ymin < cyl & bounds$ymax > cyl)
## Add the points
gg + geom_point(data=df, aes(color=inside)) + theme_bw()
我有一个散点图,我想知道如何找到置信区间线上方和下方的基因?
编辑: 可重现示例:
library(ggplot2)
#dummy data
df <- mtcars[,c("mpg","cyl")]
#plot
ggplot(df,aes(mpg,cyl)) +
geom_point() +
geom_smooth()
我不得不深入研究 github
存储库,但我终于明白了。为此,您需要了解 stat_smooth
的工作原理。在这种特定情况下,调用 loess
函数来进行平滑处理(可以使用与以下相同的过程构造不同的平滑函数):
因此,在这种情况下使用 loess
我们会做:
#data
df <- mtcars[,c("mpg","cyl"), with=FALSE]
#run loess model
cars.lo <- loess(cyl ~ mpg, df)
然后我不得不阅读 this 以了解 stat_smooth
内部是如何做出预测的。显然 hadley 在我们的案例中使用 predictdf
函数(未导出到命名空间)如下:
predictdf.loess <- function(model, xseq, se, level) {
pred <- stats::predict(model, newdata = data.frame(x = xseq), se = se)
if (se) {
y = pred$fit
ci <- pred$se.fit * stats::qt(level / 2 + .5, pred$df)
ymin = y - ci
ymax = y + ci
data.frame(x = xseq, y, ymin, ymax, se = pred$se.fit)
} else {
data.frame(x = xseq, y = as.vector(pred))
}
}
阅读以上内容后,我可以使用以下方法创建自己的 data.frame 预测:
#get the predictions i.e. the fit and se.fit vectors
pred <- predict(cars.lo, se=TRUE)
#create a data.frame from those
df2 <- data.frame(mpg=df$mpg, fit=pred$fit, se.fit=pred$se.fit * qt(0.95 / 2 + .5, pred$df))
查看 predictdf.loess
,我们可以看到置信区间的上限创建为 pred$fit + pred$se.fit * qt(0.95 / 2 + .5, pred$df)
,下限创建为 pred$fit - pred$se.fit * qt(0.95 / 2 + .5, pred$df)
。
使用这些我们可以为超出或低于这些边界的点创建一个标志:
#make the flag
outerpoints <- +(df$cyl > df2$fit + df2$se.fit | df$cyl < df2$fit - df2$se.fit)
#add flag to original data frame
df$outer <- outerpoints
df$outer
列可能是 OP 正在寻找的内容(如果它在边界之外则取值 1,否则取值 0)但为了它我将其绘制在下面。
注意上面的+
函数在这里只用于将逻辑标志转换为数字。
现在如果我们这样画:
ggplot(df,aes(mpg,cyl)) +
geom_point(aes(colour=factor(outer))) +
geom_smooth()
我们实际上可以看到置信区间内外的点。
输出:
P.S。对于任何对上下边界感兴趣的人,它们是这样创建的(推测:虽然阴影区域可能是用 geom_ribbon 或类似的东西创建的 - 这使它们更圆更漂亮):
#upper boundary
ggplot(df,aes(mpg,cyl)) +
geom_point(aes(colour=factor(outer))) +
geom_smooth() +
geom_line(data=df2, aes(mpg , fit + se.fit , group=1), colour='red')
#lower boundary
ggplot(df,aes(mpg,cyl)) +
geom_point(aes(colour=factor(outer))) +
geom_smooth() +
geom_line(data=df2, aes(mpg , fit - se.fit , group=1), colour='red')
此解决方案利用了 ggplot2 为您所做的辛勤工作:
library(sp)
# we have to build the plot first so ggplot can do the calculations
ggplot(df,aes(mpg,cyl)) +
geom_point() +
geom_smooth() -> gg
# do the calculations
gb <- ggplot_build(gg)
# get the CI data
p <- gb$data[[2]]
# make a polygon out of it
poly <- data.frame(
x=c(p$x[1], p$x, p$x[length(p$x)], rev(p$x)),
y=c(p$ymax[1], p$ymin, p$ymax[length(p$x)], rev(p$ymax))
)
# test for original values in said polygon and add that to orig data
# so we can color by it
df$in_ci <- point.in.polygon(df$mpg, df$cyl, poly$x, poly$y)
# re-do the plot with the new data
ggplot(df,aes(mpg,cyl)) +
geom_point(aes(color=factor(in_ci))) +
geom_smooth()
它需要一些调整(即最后一点获得 2
值)但我的时间有限。请注意 point.in.polygon
return 值为:
0
: 点完全在 pol 之外
1
: 点严格在 pol 内部
2
: 点位于 pol 边的相对内部
3
: point是pol 的一个顶点
所以无论值是否为 0
,只需将代码更改为 TRUE
/FALSE
应该很容易。
使用 ggplot_build
就像@hrbrmstr 的不错的解决方案一样,您实际上可以通过简单地将一系列 x 值传递给 geom_smooth
来指定应该计算误差范围的位置,并使其等于你的点的 x 值。然后,您只需查看 y 值是否在范围内。
library(ggplot2)
## dummy data
df <- mtcars[,c("mpg","cyl")]
ggplot(df, aes(mpg, cyl)) +
geom_smooth(params=list(xseq=df$mpg)) -> gg
## Find the points within bounds
bounds <- ggplot_build(gg)[[1]][[1]]
df$inside <- with(df, bounds$ymin < cyl & bounds$ymax > cyl)
## Add the points
gg + geom_point(data=df, aes(color=inside)) + theme_bw()