我有一些要平滑的数据,以使平滑点单调递减。我的数据急剧下降,然后开始稳定。这是使用R的示例
df <- data.frame(x=1:10, y=c(100,41,22,10,6,7,2,1,3,1))
ggplot(df, aes(x=x, y=y))+geom_line()
我可以使用什么好的平滑技术?另外,如果我可以强制第一个平滑点接近观察点,那就太好了。
我有一些要平滑的数据,以使平滑点单调递减。我的数据急剧下降,然后开始稳定。这是使用R的示例
df <- data.frame(x=1:10, y=c(100,41,22,10,6,7,2,1,3,1))
ggplot(df, aes(x=x, y=y))+geom_line()
我可以使用什么好的平滑技术?另外,如果我可以强制第一个平滑点接近观察点,那就太好了。
Answers:
您可以通过mgcv软件包中的mono.con()
和pcls()
函数使用具有单调性约束的惩罚样条曲线来执行此操作。之所以要摆弄些麻烦,是因为这些功能的用户友好性不如gam()
,但是下面所示的步骤主要是根据的示例进行了?pcls
修改,以适应您提供的示例数据:
df <- data.frame(x=1:10, y=c(100,41,22,10,6,7,2,1,3,1))
## Set up the size of the basis functions/number of knots
k <- 5
## This fits the unconstrained model but gets us smoothness parameters that
## that we will need later
unc <- gam(y ~ s(x, k = k, bs = "cr"), data = df)
## This creates the cubic spline basis functions of `x`
## It returns an object containing the penalty matrix for the spline
## among other things; see ?smooth.construct for description of each
## element in the returned object
sm <- smoothCon(s(x, k = k, bs = "cr"), df, knots = NULL)[[1]]
## This gets the constraint matrix and constraint vector that imposes
## linear constraints to enforce montonicity on a cubic regression spline
## the key thing you need to change is `up`.
## `up = TRUE` == increasing function
## `up = FALSE` == decreasing function (as per your example)
## `xp` is a vector of knot locations that we get back from smoothCon
F <- mono.con(sm$xp, up = FALSE) # get constraints: up = FALSE == Decreasing constraint!
现在我们需要填写传递给的对象,pcls()
其中包含我们要拟合的受约束模型的详细信息
## Fill in G, the object pcsl needs to fit; this is just what `pcls` says it needs:
## X is the model matrix (of the basis functions)
## C is the identifiability constraints - no constraints needed here
## for the single smooth
## sp are the smoothness parameters from the unconstrained GAM
## p/xp are the knot locations again, but negated for a decreasing function
## y is the response data
## w are weights and this is fancy code for a vector of 1s of length(y)
G <- list(X = sm$X, C = matrix(0,0,0), sp = unc$sp,
p = -sm$xp, # note the - here! This is for decreasing fits!
y = df$y,
w = df$y*0+1)
G$Ain <- F$A # the monotonicity constraint matrix
G$bin <- F$b # the monotonicity constraint vector, both from mono.con
G$S <- sm$S # the penalty matrix for the cubic spline
G$off <- 0 # location of offsets in the penalty matrix
现在我们终于可以进行拟合了
## Do the constrained fit
p <- pcls(G) # fit spline (using s.p. from unconstrained fit)
p
包含对应于样条曲线的基函数的系数向量。为了可视化拟合的样条曲线,我们可以根据模型在x范围内的100个位置进行预测。我们执行100个值,以便在绘图上获得一条漂亮的平滑线。
## predict at 100 locations over range of x - get a smooth line on the plot
newx <- with(df, data.frame(x = seq(min(x), max(x), length = 100)))
为了生成预测值,我们使用Predict.matrix()
,它会生成一个矩阵,使得当乘以系数时,会p
从拟合模型中得出预测值:
fv <- Predict.matrix(sm, newx) %*% p
newx <- transform(newx, yhat = fv[,1])
plot(y ~ x, data = df, pch = 16)
lines(yhat ~ x, data = newx, col = "red")
这将产生:
我将由您自己决定,以使数据成为整齐的表格,以便使用ggplot进行绘图...
您可以通过增加的基函数的维数来强制进行更紧密的拟合(以部分回答有关使第一个数据点更平滑地拟合的问题)x
。例如,设置k
等于8
(k <- 8
)并重新运行上面的代码,我们得到
您不能将k
这些数据推得更高,而且必须注意过度拟合。pcls()
在给定约束和所提供的基础函数的情况下,所有要做的就是解决惩罚最小二乘问题,它不是在为您执行平滑度选择-这不是我所知道的...)
如果要进行插值,请参阅基本R函数?splinefun
,该函数具有Hermite样条和具有单调约束的三次样条。但是,在这种情况下,由于数据并非严格单调,因此无法使用它。
splinefun
是我最初的想法,以及(我插值),但spline(x=df$x, y=df$y, n=nrow(df), method="monoH.FC")
和spline(x=df$x, y=df$y, n=nrow(df), method="hyman")
这两个引发错误
?mono.con
进一步详细介绍了该方法。
splinefun
引发错误;我刚刚意识到,您可以拟合插入数据的单调样条,而该数据本身并不是单调的。的观察值x = 6
大于y
的观察值x = 5
。您只需要忽略答案的那部分即可:-)
mono.con
返回三次样条。?pcls
有一些薄板样条和附加模型的示例,它们比上面的用户友好性差,但是如果您熟悉这些样条类型的数学,则可能会暴露更多的数学信息(我自己不是很熟悉)。
Natalya Pya最近的欺诈软件包,并基于Pya&Wood(2015)的论文“ Shape constrainedadditives model”,可以使加文出色答案中提到的过程变得更加容易。
library(scam)
con <- scam(y ~ s(x, k = k, bs = "mpd"), data = df)
plot(con)
您可以使用许多bs函数-在上面,我将mpd用于“单调递减的P样条曲线”,但它也具有单独或与单调约束一起实施凸面或凹面的功能。
plot(y~x,data=df); f=fitted( glm( y~ns(x,df=4), data=df,family=quasipoisson)); lines(df$x,f)