Вы можете сделать это с помощью наказываться шлицы с ограничениями монотонности через mono.con()
и pcls()
функций в mgcv пакете. Нам нужно немного поработать, потому что эти функции не так удобны для пользователя, как 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
содержит вектор коэффициентов для базисных функций, соответствующих сплайну. Чтобы визуализировать подобранный сплайн, мы можем предсказать по модели в 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
которая имеет сплайны Эрмита и кубические сплайны с ограничениями монотонности. В этом случае вы не можете использовать это, однако, поскольку данные не являются строго монотонными.
plot(y~x,data=df); f=fitted( glm( y~ns(x,df=4), data=df,family=quasipoisson)); lines(df$x,f)