How to adjust smoothness of spline - r

set.seed(1); x <- round(rnorm(30), 1); y <- sin(pi * x) + rnorm(30)/10
plot(x, y, main = "spline(x,y) when x has ties")
lines(spline(x, y, n = 201), col = 2)
Is there a way to adjust the smoothness of the spline? Especially from -0.5 and onwards, there are wiggly parts that could be smoother. I have looked at the documentation but there doesn't seem to be a straightforward parameter that does this (something like spar in smooth.spline).

loess is one method, but if you want to use splines, use smooth.spline, not the interpolating spline
set.seed(1);
x <- round(rnorm(30), 1);
y <- sin(pi * x) + rnorm(30)/10
plot(x, y, main = "spline(x,y) when x has ties")
sm <- smooth.spline(x, y, spar = 0.5) # play with spar
pred <- predict(sm, seq(-2, 2, by = 0.1))
lines(pred, col = "red")
There is a problem with this solution: note that in the negative region where points are less dense, the fit is not so good. loess is more local (that's what the l stands for), so it might be better.

I would use LOESS for smoothing:
lines(loess.smooth(y=spl[["y"]], x=spl[["x"]], span = 0.05), col=2)
Adjust span as needed.

Related

Creating a Smooth Line in 3D R

I have a set of 3-dimensional points, like the sample data below. I would like to create a smooth line from it. There's information out there about to smooth a 2D surface in 3D space but how would I smooth a 1D line in 3D space?
Z = seq(0, 1, 0.01)
X = rnorm(length(Z), mean = 0, sd = 0.1)
Y = 2 * Z ^ 2 + rnorm(length(Z), mean = 0, sd = 0.1)
data = data.frame(X = X, Y = Y, Z= Z)
This is an example of multivariate regression. If you happen to know that the relationship with Z should be quadratic, you can do
fit <- lm(cbind(X, Y) ~ poly(Z, 2))
But I'm assuming you don't know that, and want some kind of general smoother. I don't think loess, lowess, or gam handle multivariate regression, but you can use natural splines in lm:
library(splines)
fit <- lm(cbind(X, Y) ~ ns(Z, df = 4))
The fitted values will be returned in a two-column matrix by predict(fit).
To plot the result, you can use rgl:
library(rgl)
plot3d(X, Y, Z, col = "red")
lines3d(cbind(predict(fit), Z))

How to plot a surface with discontinuity in R using "persp" function

I want to plot a discontinuous surface using the persp function.
Here is the function:
f <- function(x, y)
{
r <- sqrt(x^2 + y^2)
out <- numeric(length(r))
ok <- r >= 1
out[ok] <- exp(-(r[ok] - 1))
return(out)
}
To get a perspective plot of the function on a regular grid, I use
x <- y <- seq(-4, 4, length.out = 50)
z <- outer(x, y, f)
persp(x, y, z, , theta = 30, phi = 30, expand = 0.5, col = "lightblue")
The resulting plot does not properly show the circular nature of discontinuity points of the surface. Any suggestion about how to obtain a better perspective plot, instead of contour plot or image?
If something interactive works for you, I would go for something like this:
library(plotly)
plot_ly(z = ~ z) %>% add_surface()
Because the circular nature is best seen from above, a phi of 90 would be best to highlight this feature, but then you lose the rest of the shape and it is pretty useless. Hence, I would go for something interactive.
persp(x, y, z, , theta = 30, phi = 30, expand = 0.5, col = "lightblue")

How to use smoothing splines in gam in the R package mgcv

The question is that is this the correct way to specify the knots in the smoothing spline in gam in mgcv?
The confusion part is that in the vignette, it says the k is the dimension of the basis used to represent the smooth term.
(Previously I thought that in the "cr" setting, the dimension of the basis is 3. After reading p. 149-150 (GAM, an introduction to R), it seems that the gam uses a set of k basis to write the cubic regression splines.)
However, in the post below, it shows that k is actually the number of knots. This is verified by the code below
# reference
# https://stackoverflow.com/questions/40056566/mgcv-how-to-set-number-and-or-locations-of-knots-for-splines
library(mgcv)
## toy data
set.seed(0); x <- sort(rnorm(400, 0, pi)) ## note, my x are not uniformly sampled
set.seed(1); e <- rnorm(400, 0, 0.4)
y0 <- sin(x) + 0.2 * x + cos(abs(x))
y <- y0 + e
## fitting natural cubic spline
cr_fit <- gam(y ~ s(x, bs = 'cr', k = 20))
cr_knots <- cr_fit$smooth[[1]]$xp ## extract knots locations
par(mfrow = c(1,2))
plot(x, y, col= "blue", main = "natural cubic spline");
lines(x, cr_fit$linear.predictors, col = 2, lwd = 2)
abline(v = cr_knots, lty = 2)
Then, to use the smoothing spline, should I assign the knots manually in the argument of gam? The attempted code is below:
## fitting natural cubic spline, smoothing spline
cr_fit <- gam(y ~ s(x, bs = 'cr', k = length(x)), knots=list(x))
cr_knots <- cr_fit$smooth[[1]]$xp ## extract knots locations
## summary plot
par(mfrow = c(1,2))
plot(x, y, col= "blue", main = "natural cubic spline");
lines(x, cr_fit$linear.predictors, col = 2, lwd = 2)
abline(v = cr_knots, lty = 2)
plot(x,cr_knots)
cr_fit$sp
Is this understanding correct?
If yes, then how can I implement the smoothing splines method with the gam in the mgcv?

obtain global maximum of a fitted smoothing spline from R function 'smooth.spline'

I smoothed my data using smooth.spline(x,y) and now I want to calculate the mode or maximum of smoothed curve.
x <- vect.1
y <- vect.2
plot(x, y, type = 'l')
smth <- smooth.spline(x, y)
lines(smth, col = 'red', lwd = 2)
My current approach is simply to look up the x which gives me the maximum y which is not so accurate. Is there a better way for doing this?
psmth <- predict(smth, x= seq(1,100, by=0.1) )
mode_psmth <- psmth$y[ which.max( psmth$y ) ]
Or even:
mode_psmth <- max(psmth$y)
If this is not "sufficiently accurate", then please explain why.

plot level lines (2 circumferences) on a 3d plot

I'm trying to plot the two circumferences with dimensions xy together with the 3d plot and colour the intersection of the two circles, how can I do that?
# objective function
x <- seq(-1,1,.1)
y <- seq(-1,1,.1)
z <- x^2 + y^2
library(scatterplot3d)
library(plotrix)
scatterplot3d(x,y,z,pch=19,color="royalblue4")
draw.circle (1,1,1)
draw.circle (1,-1,1)
I'm not really into mathematic stuff, but I'll post as answer because it might be of use and, also, is too big for a comment. Excuse any ignorance of mine, though, if I post nonsense.
#your data
library(scatterplot3d)
x <- seq(-1,1,.1)
y <- seq(-1,1,.1)
z <- x^2 + y^2
ang = 60 #angle of the 3D plot. experiment with different values
#your 3D plot, with extended xx', yy' limits
sp3d <- scatterplot3d(x, y, z, pch=19, color="royalblue4",
xlim = c(-1, 3), ylim = c(-3, 3), angle = ang)
#to use parametric equations of circles
f <- seq(-2*pi, 2*pi, 0.1)
#circle1
sp3d$points(x = 1 + 1*cos(f), y = 1 + 1*sin(f), z = rep(0, length(f)), type = "l")
#circle2
sp3d$points(x = 1 + 1*cos(f), y = -1 + 1*sin(f), z = rep(0, length(f)), type = "l")
The plot is:

Resources