绘制穿过所有数据点的平滑线

问题描述 投票:0回答:2

我正在尝试绘制一条直接穿过所有数据点的平滑线,并且具有基于另一个变量的梯度。理论上多项式插值可以完成这项工作,但我不确定如何使用 ggplot 来完成这项工作。这是我到目前为止所想到的:

数据:

 dayofweek hour impressions conversions      cvr
         1    0     3997982       352.0 8.80e-05
         1    1     3182678       321.2 1.01e-04
         1    2     2921004       248.6 8.51e-05
         1    3     1708627       115.6 6.77e-05
         1    4     1225059        98.4 8.03e-05
         1    5     1211708        62.0 5.12e-05
         1    6     1653280       150.0 9.07e-05
         1    7     2511577       309.4 1.23e-04
         1    8     3801969       397.8 1.05e-04
         1    9     5144399       573.0 1.11e-04
         1   10     5770269       675.6 1.17e-04
         1   11     6936943       869.8 1.25e-04
         1   12     7953053       996.4 1.25e-04
         1   13     8711737      1117.8 1.28e-04
         1   14     9114872      1217.4 1.34e-04
         1   15     9257161      1155.2 1.25e-04
         1   16     8437068      1082.0 1.28e-04
         1   17     8688057      1047.2 1.21e-04
         1   18     9200450      1114.0 1.21e-04
         1   19     8494295      1086.8 1.28e-04
         1   20     9409142      1092.6 1.16e-04
         1   21    10500000      1266.8 1.21e-04
         1   22     9783073      1196.4 1.22e-04
         1   23     8225267       812.0 9.87e-05

R 代码:

ggplot(d) + 
  geom_line(aes(y=impressions, x=hour, color=cvr)) +
  stat_smooth(aes(y=impressions, x=hour), method = lm, formula = y ~ poly(x, 10), se = FALSE)

所以我可以使用 geom_line 获得我想要的渐变,但它不平滑。使用 stat_smooth 我得到一条平滑的线,但它没有贯穿所有数据点,也没有我想要的梯度。关于如何实现这一目标有什么想法吗?

r ggplot2 smoothing
2个回答
64
投票

如果您希望它遍历所有点,那么您正在使用的多项式插值可能不是最好的主意。您有 24 个点,如果要遍历所有点,则需要 23 阶多项式。我似乎无法将

poly
与度数 23 一起使用,但使用较小的度数已经足以向您展示为什么这不起作用:

ggplot(d) + 
  geom_point(aes(x = hour, y = impressions, colour = cvr), size = 3) +
  stat_smooth(aes(x = hour, y = impressions), method = "lm",
              formula = y ~ poly(x, 21), se = FALSE) +
  coord_cartesian(ylim = c(0, 1.5e7))

这或多或少地经历了所有点(如果我设法使用更高阶的多项式,它确实会经历),但否则它可能不是您想要的那种平滑曲线。 更好的选择是使用 splines 进行插值。这也是一种使用多项式的插值,但它不是仅使用一个多项式(如您尝试的那样),而是使用多个多项式。它们被强制以曲线连续的方式遍历所有数据点。

据我所知,这不能直接用ggplot来完成,但可以使用

ggalt::geom_xspline
来完成。

这里我展示了一个

base
解决方案,其中样条插值是在单独的步骤中生成的:

spline_int <- as.data.frame(spline(d$hour, d$impressions))

您需要

as.data.frame
,因为
spline
返回一个列表。现在您可以在图中使用新数据
geom_line()
:

ggplot(d) + 
  geom_point(aes(x = hour, y = impressions, colour = cvr), size = 3) +
  geom_line(data = spline_int, aes(x = x, y = y))


0
投票

现在使用 ggplot 扩展包可以很容易地做到这一点,例如

geom_xspline
中的
ggalt
函数:

library(ggplot2)
library(ggalt)

ggplot(d, aes(x = hour, y = impressions)) + 
  geom_point(aes(colour = cvr), size = 3) +
  geom_xspline()

创建于 2023-08-28,使用 reprex v2.0.2

© www.soinside.com 2019 - 2024. All rights reserved.