Splines – Strategies to Avoid Spline Dip in Data Analysis

splines

First off, I'm not very experienced in math techniques, so I am wide open to suggestions.

I am working with a set of data in R. I have a curve (mostly linear at first, peaking suddenly, then decreasing.) I want to smooth it out, so I used a spline and that achieves what I want (especially the peak of the curve "off center" from the top point). But there is a dip right below the peak that I want to avoid, as its essentially linear right there. enter image description here

I kind of understand (in a non-mathematical way) why this dip has to be there, to give the curve enough time to angle upwards. But it doesn't represent that data.

Is there any way to avoid this dip? I've thought about graphing it as two separate lines (a linear and a curved one), but that isn't appealing. Is there something besides a spline? Or code I can use to get around this?

Time          Feave
0.04    138.8181818
   7    1258.636364
  14    1320.545455
  21     2110.37037
  28    13730.37037
  35    1550.909091

All I'm using is splinefun in R (so cubic)

plot(P0mM$Time,P0mM$Feave, ylab="Fe2+ uM", xlab="Time", main="0mM P", ylim=c(0,15000))
arrows(P0mM$Time, P0mM$Feave-P0mM$Festerr, P0mM$Time, P0mM$Feave+P0mM$Festerr, length=0.05, angle=90, code=3)
lines(spline(P0mM$Time,P0mM$Feave,n=200))

Best Answer

There are a number of ways to avoid such effects (e.g. smoothing splines can often be tweaked so as to avoid a dip, or maybe some form of monotonic spline to the left of the peak will be needed), but I think in this particular case a simple approach might be to transform (perhaps take logs or square roots), fit a spline on that scale and transform back.

Unimodal splines exist and may suit you better.

I haven't used it (edit: well, I have now! see below), but I believe the package uniReg (on CRAN) will do unimodal splines.

...

enter image description here

Some code. Here I had previously but unimaginatively read your data into a data frame called a:

library(uniReg)
z=seq(min(a$Time),max(a$Time),length=201)
uf=with(a,unireg(Time,Fe2.,g=5,sigma=1))
plot(Fe2.~Time,a,ylim=c(0,14500))
lines(z,uf$unimod.func(z))

The author also has a paper on unimodal splines - since published by the look, but I'll let you chase the paper up if you want it - but doesn't seem to mention it in the package documentation.