如何用arctan函数拟合近似给定数据集的曲线?
Hey there! Let's work through fitting your dataset with an arctangent function—since your data follows that classic sigmoidal, saturating shape of arctan(x), this is a great choice. I'll use R for all examples, matching your existing code.
Step 1: Organize Your Data
First, let's wrap your data into a data frame for easier handling:
xs <- seq(1000,50000,by=1000) data <- c(0.101, 0.169, 0.209, 0.256, 0.289, 0.373, 0.391, 0.418, 0.477, 0.528, 0.579, 0.570, 0.602, 0.657, 0.690, 0.720, 0.747, 0.764, 0.781, 0.811, 0.842, 0.847, 0.864, 0.889, 0.871, 0.894, 0.897, 0.915, 0.926, 0.931, 0.932, 0.940, 0.950, 0.963, 0.956, 0.967, 0.967, 0.963, 0.971, 0.980, 0.986, 0.988, 0.986, 0.985, 0.993, 0.992, 0.994, 0.991, 0.995, 0.993) df <- data.frame(x = xs, y = data)
Step 2: Choose an Arctangent Model
The standard arctan(x) ranges from -π/2 to π/2, but your data starts around 0.1 and saturates near 1. We need a scaled, shifted version of the function to match this. A flexible model for your data is:
y = k + m * atan(n * x)
k: The baseline (y-value when x approaches 0)m: Scales the arctan output to match your data's rangen: Controls how quickly the curve rises (smaller values = slower rise)
Based on your data's trend, we can guess initial parameters:
k ≈ -0.03(since x=1000 gives y≈0.1, andatan(n*1000)will be small)m ≈ 0.65(to scale the arctan's max output (~π/2 ≈1.57) to reach near 1)n ≈ 0.0002(son*50000 ≈10, whereatan(10)is close to π/2)
Step 3: Fit the Model with Nonlinear Least Squares
We'll use R's nls() function for nonlinear fitting. If you run into convergence issues, the nlsLM() function from the minpack.lm package is more robust:
Option 1: Basic nls()
# Define the model arctan_model <- y ~ k + m * atan(n * x) # Fit with initial guesses fit <- nls(arctan_model, data = df, start = list(k = -0.03, m = 0.65, n = 0.0002)) # View fit details summary(fit)
Option 2: Robust Fit with nlsLM()
# Install the package if you haven't already # install.packages("minpack.lm") library(minpack.lm) fit_lm <- nlsLM(arctan_model, data = df, start = list(k = -0.03, m = 0.65, n = 0.0002)) summary(fit_lm)
The summary will give you parameter estimates, standard errors, and goodness-of-fit metrics like the residual standard error.
Step 4: Visualize the Fit
Let's plot your original data alongside the fitted curve to check how well it matches:
# Generate predicted values from the fit df$y_pred <- predict(fit, newdata = df) # Create the plot plot(df$x, df$y, pch = 16, col = "steelblue", main = "Arctangent Fit to Your Data", xlab = "x", ylab = "y") lines(df$x, df$y_pred, col = "firebrick", lwd = 2) legend("bottomright", legend = c("Original Data", "Fitted Arctan Curve"), col = c("steelblue", "firebrick"), pch = c(16, NA), lty = c(NA, 1))
Step 5: Evaluate the Fit
To make sure the fit is good, check the residuals (differences between observed and predicted values):
residuals <- df$y - df$y_pred plot(df$x, residuals, pch = 16, col = "gray", main = "Residuals of Arctan Fit", xlab = "x", ylab = "Residual") abline(h = 0, col = "firebrick", lwd = 2)
If residuals are randomly scattered around 0 (no obvious patterns), the model is a good fit.
Bonus: Try a Shifted Arctan Model
If you want to account for a horizontal shift (moving the "inflection point" of the curve), use this model instead:
y = a * atan(b*(x - c)) + d
You can guess initial parameters (e.g., a=0.5, b=0.0001, c=15000, d=0.5) and fit it the same way as above. Compare AIC values between models—lower AIC means a better fit.
内容的提问来源于stack exchange,提问作者Andrew Davidson

