【问题标题】:Unexpected result while using lowess to smooth a data.table column in R使用lowess平滑R中的data.table列时出现意外结果
【发布时间】:2021-12-20 21:44:29
【问题描述】:

我有一个 data.table test_dt,我想在其中使用 lowess 函数平滑 y 列。

test_dt <- structure(list(x = c(28.75, 30, 31.25, 32.5, 33.75, 35, 36.25, 
37.5, 38.75, 40, 41.25, 42.5, 43.75, 45, 46.25, 47.5, 48.75, 
50, 52.5, 55, 57.5, 60, 62.5, 63.75, 65, 67.5, 70, 72.5, 75, 
77.5, 80, 82.5, 85, 87.5, 90, 92.5, 95, 97.5, 100, 102.5, 103.75, 
105, 106.25, 107.5, 108.75, 110, 111.25, 112.5, 113.75, 115, 
116.25, 117.5, 118.75, 120, 121.25, 122.5, 125, 130, 135, 140, 
145), y = c(116.78, 115.53, 114.28, 113.05, 111.78, 110.53, 109.28, 
108.05, 106.78, 105.53, 104.28, 103.025, 101.775, 100.525, 99.28, 
98.05, 96.8, 95.525, 93.1, 90.65, 88.225, 85.775, 83.35, 82.15, 
80.9, 78.5, 76.075, 73.675, 71.25, 68.85, 66.5, 64.075, 61.725, 
59.4, 57.075, 54.725, 52.475, 50.225, 48, 45.75, 44.65, 43.55, 
42.475, 41.45, 40.35, 39.275, 38.25, 37.225, 36.175, 35.175, 
34.175, 33.225, 32.275, 31.3, 30.35, 29.45, 27.625, 24.175, 21, 
18.125, 15.55), z = c(116.778248424972, 115.531456655985, 114.284502467544, 
113.034850770519, 111.784500981402, 110.533319511795, 109.284500954429, 
108.034850457264, 106.784502297216, 105.531265565238, 104.278221015846, 
103.026780249377, 101.775992395759, 100.528761292272, 99.2853168637851, 
98.043586202838, 96.8021989104315, 95.5702032427799, 93.1041279347743, 
90.6575956222915, 88.2179393348852, 85.783500434839, 83.3503011023971, 
82.136280706039, 80.922846825298, 78.4965179152157, 76.0823895453039, 
73.6686672097464, 71.264486719796, 68.8702598156142, 66.4865368523571, 
64.1182523898466, 61.7552221811808, 59.4004347738795, 57.0823289450761, 
54.7908645949795, 52.5071096685879, 50.2308279167219, 47.9940967492558, 
45.7658417529877, 44.6514226583931, 43.5622751034012, 42.4876666190815, 
41.4173110074806, 40.3555584369672, 39.3004471381618, 38.2552969838653, 
37.2202353638959, 36.1963659189447, 35.1889616530209, 34.2004259883859, 
33.2295174626826, 32.2669278456991, 31.3171387914754, 30.3742375589802, 
29.4555719783757, 27.6243725086786, 23.9784367995753, 27.625, 
27.625, 27.625)), row.names = c(NA, -61L), class = c("data.table", 
"data.frame"))

如下图所示,我得到了一个意想不到的结果。预期结果是下图中的线(z 列)应紧跟点(y 列)。

这是我的代码 -

library(data.table)
library(ggplot2)
test_dt[, z := lowess(x = x, y = y, f = 0.1)$y]
ggplot(test_dt) + geom_point(aes(x, y)) + geom_line(aes(x, z))

第一季度。有人可以建议为什么lowess 没有正确平滑吗?

第二季度。由于lowess 没有按预期工作,R 中是否还有其他函数可以更有效地平滑y 列而不产生尖峰(就像lowess 在边界点上所做的那样)?

【问题讨论】:

  • 是否打算使用geom_line(aes(x, z)) 而不是geom_line(aes(x, y))
  • 当你说“更有效地解决这个问题”时,你到底在说什么“问题”?您的观点似乎不需要太多平滑。在观察数据的边界上平滑总是很困难。
  • 我想平滑y列,使所有y点都落在一条平滑线上。
  • 我认为这与您使用的非常小的跨度(0.1)有关。如果您尝试 f=1/4 或 f=1/3,则平滑线非常好
  • 另外,如果你使用 test_dt[, z := loess(y ~ x, span = 0.1)$y] ,你会得到一个很好的平滑

标签: r ggplot2 smoothing


【解决方案1】:

您可以改用loess

test_dt[, z := predict(loess(y ~ x, data = test_dt))]

ggplot(test_dt) + geom_point(aes(x, y)) + geom_line(aes(x, z))

但请注意,如果您只想绘制线条,这正是 geom_smooth 使用的方法,因此即使不创建 z 列,您也可以这样做:

ggplot(test_dt, aes(x, y)) + geom_point() + geom_smooth()
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

reprex package 创建于 2021-11-07 (v2.0.0)

【讨论】:

    【解决方案2】:

    通过将迭代次数保持为零来解决问题。lowess 在迭代保持为零时的行为类似于 loess

    test_dt[, z := lowess(x = x, y = y, f = 0.1, iter=0)$y]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-07
      • 1970-01-01
      • 2019-05-12
      • 2017-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多