4
$\begingroup$

I have a monotonically-increasing curve whose functional form is not known a priori and would like to compute the curve's slope at the rightmost endpoint. Typically, when the functional form is known, the slope can be computed via a tangent line at a given point.

Here is a plot of the data:

enter image description here

Here is the actual data:

specs  means
1      1 1.0000
2      2 1.7531
3      3 2.3139
4      4 2.7412
5      5 3.0622
6      6 3.3042
7      7 3.4871
8      8 3.6232
9      9 3.7090
10    10 3.7882
11    11 3.8439

If the curve was a straight line, the slope could be easily computed by selecting any two points. A naive approach then would be to take the last two points on the curve and calculate the slope from the secant line connecting those points. From the data, the slope would be

m = (3.8439 - 3.7882) / (11 - 10)
  = 0.0557

I am wondering if there is a better way. A linear regression computed on a number of terminal data points seems like a plausible solution. Are there any other approaches?

$\endgroup$
3
$\begingroup$

You could fit a GP to those points. A GP is differentiable (see Rasmussen & Williams and Differentiating Gaussian Processes), so if you fit a GP with the appropriate kernel (calculated using the links above), you'd be able to predict the derivatives along with errors. I can post some python code to do this if you'd like.

A very rough way to obtain derivatives on the other hand, is to fit a (smooth) spline, predict, and calculate the forward difference. For example:

y <- c(1.0000, 1.7531, 2.3139, 2.7412, 3.0622, 3.3042, 3.4871, 3.6232, 3.7090, 3.7882, 3.8439)
model <- smooth.spline(1:length(y), y)
x_pred <- seq(1, length(y), 0.1)
y_pred <- predict(model, x_pred)$y

plot(x_pred, y_pred, type = "l", lty = 2, main = "Predicted Line")
points(1:length(y), y, pch = 20)

Predicted Line

plot(x_pred[-1], diff(y_pred)/diff(x_pred), main = "Derivative", type = "l", lty = 2)

Derivative

You can then replace the domain with whatever you like.

$\endgroup$
  • 1
    $\begingroup$ Thanks! I do indeed intend to fit splines and GPs to my data via the 'mgcv' R package with is highly flexible in the types of semiparametric models that can be fitted. First, I wanted a "quick-and-dirty" approach. You have clearly provided a logical way forward in this regard. $\endgroup$ – compbiostats Oct 29 '18 at 19:04
  • 1
    $\begingroup$ You don't need to do the finite difference yourself. The predict() method for "smooth.spline" objects has a deriv argument which you can set to deriv = 1 to get back the first derivatives of the estimated smooth at a set of prediction points. $\endgroup$ – Gavin Simpson Oct 29 '18 at 21:06
1
$\begingroup$

You can get analytical (for some of the basis types) or finite difference-based derivatives for shape constrained splines fitted using the scam package:

library('mgcv')
library('scam')
df <- data.frame(y = c(1.0000, 1.7531, 2.3139, 2.7412, 3.0622, 3.3042, 3.4871, 
                       3.6232, 3.7090, 3.7882, 3.8439),
                 x = 1:11)
m <- scam(y ~ s(x, bs = 'mpi'), data = df) # monotone, increasing p spline
plot(m)

enter image description here

The derivatives are computed (at the data observations it appears) using the derivative.scam() function:

> derivative.scam(m)
$d
            [,1]
 [1,] 0.57554768
 [2,] 0.43061351
 [3,] 0.32688012
 [4,] 0.24835810
 [5,] 0.18547120
 [6,] 0.13410582
 [7,] 0.09547508
 [8,] 0.07230056
 [9,] 0.06204719
[10,] 0.05574972
[11,] 0.02868104

$se.d
 [1] 0.006800555 0.006249082 0.004984349 0.003176170 0.003977485 0.003943232
 [7] 0.002818097 0.002757698 0.004023484 0.007457367 0.005102704
$\endgroup$
  • $\begingroup$ Would it not be necessary here to check that the default basis dimension (i.e., k = 10, not specified explicitly in you scam() call) results in a sufficiently smooth spline fit, or is that only for prediction of the response? Using scam.check() the plots look good (given the amount of data at hand), but it may be appropriate to always check. If the fit is not adequate, then try doubling k $\endgroup$ – compbiostats Nov 2 '18 at 13:34
  • $\begingroup$ Well yes you should always check, but i) I doubt CV answers will ever contain a full analysis, and ii)iven the shape of the function that you showed, k = 10 is plenty and I trust the penalty to shrink the complexity of the spline in this case. $\endgroup$ – Gavin Simpson Nov 2 '18 at 15:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.