Poor Bspline estimation for variables with short range I am recently surprised to observe a fact that, in a simple univariate regression model, the Bspline estimator performs NOT well if the range of the variable is narrow. Namely, let's consider estimating the following cross-sectional regression model
$$Y_i=m(X_i)+u_i, \ i=1,...,n,$$
where $n$ is the sample size, $Y_i$ is the dependent variable, $X_i$ is a univariate independent variable, and $u_i$ is the random error such that $E(u_i|X_i)=0$. Here, $m(\cdot)$ is an unknown conditional mean function, i.e., $m(x)=E(Y_i|X_i=x)$ for some $x$, and we assume $m(\cdot)$ is smooth.
Using Bspline estimator, we can approximate $m(X_i)\approx \sum_{l=1}^{L_{n}}\phi(X_i)\beta_l$, where $\phi(\cdot)$ is a known basis function and $\beta_l$ are unknown coefficients to be estimated. $L_n$ is the number of knots placed on the range of $X$, requiring us to specify boundary knots (knots on the boundary points of $X$) and interior knots (knots on the interior support of $X$, excluding the boundary points). For instance, if the range of $X$ is $[0,1]$, then the boundary knots are $[0,1]$, and the interior knots are, say, $(0.25,0.5,0.75)$. One can easily employ the package spline to construct $\phi(X_i)$, and estimate $\beta_l$ through OLS.
Question: The Bspline estimation is often very well by assuming the range of $X$ is relatively large, say $X\in [-1,1]$. However, I just found that the estimation becomes poor if the range of $X$ is narrow, say $X\in [0,0.3]$, which can be true in practice. I attached my code below for your reference. The poor performance remains regardless of how many interior knots we choose to place. Any suggestion on the issue here?
library(splines)
#---generating DGP by let x1~U(0,0.3):

n <- 500
x1 <- runif(n, 0, 0.3)
m1 <- x1^2

u <- rnorm(n, 0, 0.5)
y <- m1+u

Q <- cbind(x1)

#---obtain the boundary of x1:
knots.range.x=t(apply(Q, 2, range)); 

#---select one interior knot:
int.knots.x1 <- c(0.15)

#---create a matrix for the basis functions:
PhiX <- bs(Q[, 1], knots = int.knots.x1, degree=3, intercept = T, 
           Boundary.knots = c(knots.range.x[1, 1], knots.range.x[1, 
                                                                 2]))

#---estimate coefficients of beta:
ols.model <- lm(y ~ PhiX-1)
beta <- ols.model$coefficients

#---plot estimated function against the true one:
plot(x1, m1, type='p')
m1.hat <- PhiX%*%beta
points(x1, m1.hat, col='red', lty=2)
```


A picture says it all.

The scatter of values around any possible reasonably smooth curve through these points is so great as to obscure any underlying trend in their average value (conditional expectation).
The right hand plot shows that if data could be generated (collected) for a wider range of the explanatory values x1, the (quadratic) variation in the regression might become detectable.
If you remain limited to the original narrow range, you would need a sample of size $n\approx 100,000$ to detect this trend reliably using the least squares model $E[Y]=\beta_0+\beta_1 X_1 + \beta_2 X_1^2.$  This is neither a limitation of least squares nor of the model formulation (spline or otherwise): it merely reflects the difficulty of detecting this tiny signal amidst all the noise.
