These examples will highlight the important differences in curve fitting between the 3 methods. We will work with the same sine wave data for all 3 examples.

Problems:

Taylor We are nowhere near the fit of the entire function, merely close to the one point of interest, in this case the mean value of x. NNS fits the entire function.

Linear Regression The problem with linear segments is the gaps between segments. These gaps close as the number of segments is increased, but will never be continuous due to the minimum number of observations required for a regression. NNS requires significantly less steps than corresponding linear segmentation.

library(NNS)
library(pracma)

x = seq(0, 4*pi, pi/100)
y = sin(x)
N = 5
par(mfrow = c(3, N))

# NNS
for(i in 1:N) {
    NNS.reg(x, y, order = i)
}

# Taylor
f.x = function(x) sin(x)
for (i in 1:N) {
    p <- taylor(f.x, mean(x), i)
    yp <- polyval(p, x)
    plot(x, y, col = 'steelblue', ylim = c(-1.5, 1.5), main = paste0("Taylor Degree ", i))
    lines(x, yp, col = "red", type = "l", lwd = 3)
}

# Linear Regression Segments
# Segment data dynamically based on N
xy = data.frame(x = x, y = y)

for (i in 1:N) {
    if (i == 1) {
        # Single linear regression
        plot(xy$x, xy$y, col = 'steelblue', main = "1 Linear Regression")
        abline(lm(y ~ x, data = xy), col = 'red', lwd = 3)
    } else {
        # Cut the data into 'i' equal segments
        xy$grp <- cut(xy$x, breaks = i, include.lowest = TRUE)
        
        # Fit a model with interaction (x * grp) for independent slopes/intercepts
        m <- lm(y ~ x * grp, data = xy)
        xy$pred <- predict(m)
        
        plot(xy$x, xy$y, col = 'steelblue', main = paste(i, "Linear Regressions"))
        
        # Plot each segment separately to avoid connecting lines across breaks
        for (g in levels(xy$grp)) {
            dat <- subset(xy, grp == g)
            dat <- dat[order(dat$x), ]
            lines(dat$x, dat$pred, col = 'red', lwd = 3)
        }
    }
}