R中的小数据集的样条函数

时间:2016-05-11 21:53:27

标签: r spline

我一直在尝试使用R中可用的各种样条函数来表征非常小的数据集。我想,如果数据集大得多,任何数量的曲线都会像我预期的那样表现,但这种情况下的数据是有限的。下面的代码显示了我正在使用的数据类型的示例:

library(ggplot2); library(stats)

dat <- data.frame(x = c(0.333, 0.5, 1, 2, 3, 4, 5),
                  y = c(5.875e-03, 1.225e-02, 3.902e-02, 8.942e-03,
                        4.277e-03, 1.938e-03, 1.131e-03))


mod <- splinefun(dat$x, dat$y, method = "monoH.FC")
mod <- data.frame(x = seq(0.333, 5, by = 0.1), y = mod(seq(0.333, 5, by = 0.1)))

ggplot() + geom_point(data = dat, aes(x = x, y = y)) +
geom_line(data = mod, aes(x = x, y = y))

Curve example

到目前为止,单调的Hermite样条是最合适的,但它仍然存在一些问题。

直观地说,我可以告诉你这里的曲线应该是什么样的。它的最大值应为x = 1,并且不应该在x = 2.5下降。曲线似乎不应该难以重新创建;它是不对称的,具有左倾斜和可预测的尾部。

是否有一种“更好”的方法来生成一个更合适的样条函数(我假设是)一个常见的数据集,或者,是否有比曲线拟合小数据集更好的工具?

1 个答案:

答案 0 :(得分:0)

听起来你所追求的是使拟合更接近线性,我认为你可以通过将中点插值作为一个真正的点来强迫它:

dat2 = data.frame(x = union(dat$x,dat$x - c(0,diff(dat$x)/2)), 
                  y = interp1(dat$x,dat$y,xi = union(dat$x,dat$x - c(0,diff(dat$x)/2))))

(此处interp1可能不需要,union(dat$y,dat$y - c(0,diff(dat$y)/2))也应该这样做,但上面的代码可以使用。)

编辑:注意,为了使diff正常工作,您需要先正确订购数据

这会创建一个新的data.frame,其中的点数位于之前的点之间,如果现在使用它进行样条化,则表示您的权重更加线性

EDIT2:你也可以用这种方式使用权重平滑样条,并将点的权重设置在低于主要点的权重之间:

mod <- splinefun(dat$x, dat$y,method = 'monoH.FC')
mod2 <- data.frame(x = seq(0.333, 5, by = 0.1), y = mod(seq(0.333, 5, by = 0.1)))


# A set of weights, where each point in-between is weighted half as much
dat2$w <- rep(c(0.5,1),ceiling(length(dat2$x)/2))[-1]

# Smoothing Spline
modelspline <- smooth.spline(dat2$x, dat2$y,dat2$w)

# Plot points
xplot <- seq(min(dat2$x),max(dat2$x),by = 0.1)

# And Plot comparison
ggplot() + 
  geom_point(data = dat, aes(x = x, y = y)) + 
  geom_line(data = mod2, aes(x = x, y = y)) + 
  geom_line(data = data.frame(predict(modelspline,xplot)),
        aes(x = x, y = y),color = 'red')