Analisis data pertumbuhan, baik pada bidang biologi, pertanian, maupun ekonomi, sering kali memperlihatkan pola yang tidak dapat dijelaskan secara memadai oleh model linear sederhana. Pertumbuhan organisme hidup, misalnya tanaman atau hewan, biasanya mengalami fase-fase tertentu: fase awal dengan pertumbuhan lambat, fase percepatan, fase pertumbuhan maksimal, hingga fase melambat ketika mendekati batas biologis atau kapasitas lingkungan. Pola yang demikian membentuk kurva yang bersifat nonlinear, sehingga model nonlinear menjadi pilihan yang lebih tepat untuk menjelaskannya.
Dalam laporan ini, dilakukan studi pada dataset nyata berupa pertumbuhan pohon jeruk (Orange) yang tersedia di R. Analisis mencakup penerapan model nonlinear menggunakan fungsi nls(), estimasi parameter-parameter penting, interpretasi hasil dalam konteks biologis, serta evaluasi goodness-of-fit melalui ukuran statistik seperti SSE, R², dan AIC. Selain itu, sebagai pembanding, dilakukan pula pemodelan regresi linear sederhana untuk menilai sejauh mana pendekatan linear dapat (atau tidak dapat) mewakili dinamika pertumbuhan.
Tidak hanya terbatas pada data nyata, laporan ini juga menyertakan simulasi data pertumbuhan eksponensial, misalnya untuk menggambarkan dinamika pertumbuhan populasi bakteri. Simulasi ini berfungsi untuk menguji sejauh mana nls() dapat mengestimasi parameter dari data yang diketahui model dasarnya. Hasil simulasi akan menunjukkan kekuatan metode nonlinear dalam mengidentifikasi parameter meskipun terdapat gangguan (noise) dalam data.
Dengan demikian, laporan ini tidak hanya memberikan gambaran teknis tentang penerapan regresi nonlinear dalam R, tetapi juga menekankan aspek interpretasi biologis/ekonomis dari parameter, perbandingan performa dengan model linear, serta implikasi praktis dalam pemodelan data pertumbuhan di dunia nyata.
Orange (pertumbuhan pohon
jeruk)Dataset Orange bawaan R berisi pengukuran keliling
batang pohon (circumference) pada beberapa pohon pada usia
(age) tertentu. Pola umumnya memperlihatkan pertumbuhan
nonlinier (cepat di awal kemudian melambat).
Rumus sederhana yang akan dicoba:
\[y = \frac{Asym}{1 + e^{(xmid - x)/scale}}\]
atau model asimptotik (monomolecular / asymptotic):
\[y = Asym - A e^{-b x}\]
\[y = \beta_0 + \beta_1 x + \varepsilon\]
data("Orange")
Orange <- as_tibble(Orange)
Orange
## # A tibble: 35 × 3
## Tree age circumference
## <ord> <dbl> <dbl>
## 1 1 118 30
## 2 1 484 58
## 3 1 664 87
## 4 1 1004 115
## 5 1 1231 120
## 6 1 1372 142
## 7 1 1582 145
## 8 2 118 33
## 9 2 484 69
## 10 2 664 111
## # ℹ 25 more rows
# Plot eksplorasi keseluruhan
ggplot(Orange, aes(x = age, y = circumference, color = factor(Tree))) +
geom_point() +
geom_line() +
labs(color = "Tree", title = "Data Orange: circumference vs age", x = "Age (days)", y = "Circumference (mm)") +
theme_minimal()
Interpretasi eksplorasi: dari plot terlihat hubungan nonlinier: laju pertumbuhan menurun pada usia lebih tua.
nls()Kita akan mencoba model asimptotik yang sering cocok untuk
pertumbuhan pohon: paket base menyediakan fungsi self-start
SSasymp atau SSlogis. Di sini gunakan model
logistic self-start (SSlogis) dan model asimptotik
(SSasymp).
# Model logistic (self-start)
fit_logis <- nls(circumference ~ SSlogis(age, Asym, xmid, scal), data = Orange)
summary(fit_logis)
##
## Formula: circumference ~ SSlogis(age, Asym, xmid, scal)
##
## Parameters:
## Estimate Std. Error t value Pr(>|t|)
## Asym 192.69 20.24 9.518 7.48e-11 ***
## xmid 728.76 107.30 6.792 1.12e-07 ***
## scal 353.53 81.47 4.339 0.000134 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 23.37 on 32 degrees of freedom
##
## Number of iterations to convergence: 0
## Achieved convergence tolerance: 2.201e-06
# Model asymptotic (self-start)
fit_asymp <- nls(circumference ~ SSasymp(age, Asym, R0, lrc), data = Orange)
summary(fit_asymp)
##
## Formula: circumference ~ SSasymp(age, Asym, R0, lrc)
##
## Parameters:
## Estimate Std. Error t value Pr(>|t|)
## Asym 559.283 706.984 0.791 0.435
## R0 10.819 13.806 0.784 0.439
## lrc -8.344 1.573 -5.304 8.21e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 23.94 on 32 degrees of freedom
##
## Number of iterations to convergence: 0
## Achieved convergence tolerance: 2.329e-06
# Ekstrak koef
coef(fit_logis)
## Asym xmid scal
## 192.6873 728.7552 353.5326
coef(fit_asymp)
## Asym R0 lrc
## 559.28250 10.81873 -8.34403
Interpretasi parameter:
- Asym: nilai asimptotik (perkiraan nilai keliling maksimum
ketika usia sangat besar).
- xmid (logistic): umur pada titik tengah pertumbuhan
(titik infleksi).
- scal (logistic): skala waktu yang mengendalikan
kemiringan pada titik tengah.
- R0, lrc (SSasymp): parameter transformasi
terkait intercept efektif dan laju pertumbuhan.
# Fungsi bantu
gof_stats <- function(model, data, resp){
pred <- predict(model, newdata = data)
resid <- data[[resp]] - pred
SSE <- sum(resid^2)
SST <- sum((data[[resp]] - mean(data[[resp]]))^2)
R2_pseudo <- 1 - SSE / SST
AIC_val <- AIC(model)
tibble(SSE = SSE, SST = SST, R2_pseudo = R2_pseudo, AIC = AIC_val)
}
gof_logis <- gof_stats(fit_logis, Orange, "circumference")
gof_asymp <- gof_stats(fit_asymp, Orange, "circumference")
bind_rows(Logistic = gof_logis, Asymptotic = gof_asymp, .id = "model")
## # A tibble: 2 × 5
## model SSE SST R2_pseudo AIC
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Logistic 17480. 112366. 0.844 325.
## 2 Asymptotic 18335. 112366. 0.837 326.
Orange_plot <- Orange %>%
mutate(pred_logis = predict(fit_logis, newdata = Orange),
pred_asymp = predict(fit_asymp, newdata = Orange))
ggplot(Orange_plot, aes(x = age, y = circumference)) +
geom_point(aes(color = factor(Tree))) +
geom_line(aes(y = pred_logis), size = 1, linetype = "dashed") +
geom_line(aes(y = pred_asymp), size = 1, linetype = "solid") +
labs(title = "Model Nonlinear: Logistic (dashed) vs Asymptotic (solid)", x = "Age", y = "Circumference") +
theme_minimal()
fit_lm <- lm(circumference ~ age, data = Orange)
summary(fit_lm)
##
## Call:
## lm(formula = circumference ~ age, data = Orange)
##
## Residuals:
## Min 1Q Median 3Q Max
## -46.310 -14.946 -0.076 19.697 45.111
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 17.399650 8.622660 2.018 0.0518 .
## age 0.106770 0.008277 12.900 1.93e-14 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 23.74 on 33 degrees of freedom
## Multiple R-squared: 0.8345, Adjusted R-squared: 0.8295
## F-statistic: 166.4 on 1 and 33 DF, p-value: 1.931e-14
# GOF untuk linear
pred_lm <- predict(fit_lm, newdata = Orange)
SSE_lm <- sum((Orange$circumference - pred_lm)^2)
SST <- sum((Orange$circumference - mean(Orange$circumference))^2)
R2_lm <- 1 - SSE_lm / SST
AIC_lm <- AIC(fit_lm)
tibble(model = "Linear", SSE = SSE_lm, R2 = R2_lm, AIC = AIC_lm)
## # A tibble: 1 × 4
## model SSE R2 AIC
## <chr> <dbl> <dbl> <dbl>
## 1 Linear 18595. 0.835 325.
gof_table <- bind_rows(
Linear = tibble(SSE = SSE_lm, R2 = R2_lm, AIC = AIC_lm),
Logistic = gof_logis %>% rename(R2 = R2_pseudo),
Asymptotic = gof_asymp %>% rename(R2 = R2_pseudo),
.id = "model"
)
gof_table
## # A tibble: 3 × 5
## model SSE R2 AIC SST
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Linear 18595. 0.835 325. NA
## 2 Logistic 17480. 0.844 325. 112366.
## 3 Asymptotic 18335. 0.837 326. 112366.
Orange_plot2 <- Orange_plot %>%
mutate(pred_lm = pred_lm)
ggplot(Orange_plot2, aes(x = age, y = circumference)) +
geom_point(aes(color = factor(Tree))) +
geom_line(aes(y = pred_lm), size = 1, linetype = "dotdash") +
geom_line(aes(y = pred_logis), size = 1, linetype = "dashed") +
geom_line(aes(y = pred_asymp), size = 1, linetype = "solid") +
labs(title = "Perbandingan Model: Linear (dotdash), Logistic (dashed), Asymptotic (solid)", x = "Age", y = "Circumference") +
theme_minimal()
set.seed(123)
A_true <- 2
b_true <- 0.6
sigma <- 0.5
t <- seq(0, 5, by = 0.2)
y_true <- A_true * exp(b_true * t)
y_obs <- y_true + rnorm(length(t), mean = 0, sd = sigma)
dat_sim <- tibble(t = t, y = y_obs, y_true = y_true)
ggplot(dat_sim, aes(x = t, y = y)) +
geom_point() +
geom_line(aes(y = y_true), linetype = "dashed") +
labs(title = "Simulasi: Pertumbuhan Eksponensial dengan Noise", x = "Time", y = "Observasi y") +
theme_minimal()
lin_start <- lm(log(pmax(y, .0001)) ~ t, data = dat_sim)
A_start <- exp(coef(lin_start)[1])
b_start <- coef(lin_start)[2]
fit_exp <- nls(y ~ A * exp(b * t), data = dat_sim, start = list(A = A_start, b = b_start))
summary(fit_exp)
##
## Formula: y ~ A * exp(b * t)
##
## Parameters:
## Estimate Std. Error t value Pr(>|t|)
## A 2.073357 0.056813 36.49 <2e-16 ***
## b 0.589045 0.006321 93.19 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4407 on 24 degrees of freedom
##
## Number of iterations to convergence: 2
## Achieved convergence tolerance: 4.297e-07
coef(fit_exp)
## A b
## 2.0733568 0.5890452
pred_sim <- predict(fit_exp, newdata = dat_sim)
SSE_sim <- sum((dat_sim$y - pred_sim)^2)
SST_sim <- sum((dat_sim$y - mean(dat_sim$y))^2)
R2_sim <- 1 - SSE_sim / SST_sim
tibble(SSE = SSE_sim, R2 = R2_sim)
## # A tibble: 1 × 2
## SSE R2
## <dbl> <dbl>
## 1 4.66 0.998
dat_sim <- dat_sim %>% mutate(pred = pred_sim)
ggplot(dat_sim, aes(x = t)) +
geom_point(aes(y = y)) +
geom_line(aes(y = y_true), linetype = "dashed") +
geom_line(aes(y = pred), linetype = "solid") +
labs(title = "Hasil Fit: Model Eksponensial pada Data Simulasi", y = "y") +
theme_minimal()
Berdasarkan hasil analisis yang telah dilakukan, dapat disimpulkan bahwa model nonlinear memiliki kemampuan yang jauh lebih baik dalam menjelaskan dinamika pertumbuhan dibandingkan dengan model linear sederhana. Pada studi data nyata menggunakan dataset Orange, model nonlinear (misalnya logistic maupun asymptotic) menunjukkan nilai SSE yang lebih rendah dan R² pseudo yang lebih tinggi dibandingkan model linear. Hal ini menegaskan bahwa pola pertumbuhan yang bersifat melambat pada usia lebih tua tidak dapat ditangkap oleh regresi linear, tetapi dapat diakomodasi dengan baik oleh model nonlinear yang memiliki bentuk kurva sesuai dengan mekanisme biologis pertumbuhan.
Selain itu, parameter-parameter yang dihasilkan oleh model nonlinear juga memberikan informasi yang lebih bermakna secara biologis. Misalnya, parameter Asym menunjukkan kapasitas pertumbuhan maksimum yang dapat dicapai, sedangkan xmid atau lrc berkaitan dengan titik percepatan atau laju pertumbuhan. Interpretasi ini sangat penting bagi penelitian biologi, pertanian, maupun ekonomi, karena memberikan pemahaman tentang batasan dan dinamika suatu sistem.
Pada bagian simulasi dengan data pertumbuhan eksponensial, metode nls() terbukti mampu mengestimasi parameter dasar (A dan b) dengan nilai yang mendekati parameter sebenarnya, meskipun data terkontaminasi oleh noise. Hal ini memperlihatkan bahwa regresi nonlinear cukup andal dalam mengidentifikasi pola dasar pertumbuhan, asalkan diberikan tebakan awal parameter yang memadai. Goodness-of-fit pada simulasi juga menunjukkan hasil yang sangat baik dengan nilai R² pseudo yang tinggi.
Secara keseluruhan, analisis ini menegaskan bahwa regresi nonlinear merupakan pendekatan yang lebih sesuai dalam konteks data pertumbuhan, baik untuk studi nyata maupun simulasi. Model linear memang dapat digunakan sebagai pendekatan awal, namun keterbatasannya sangat jelas terlihat ketika data menunjukkan kurva pertumbuhan yang kompleks. Oleh karena itu, penggunaan model nonlinear sangat direkomendasikan dalam penelitian dan praktik yang berkaitan dengan analisis pertumbuhan biologis maupun fenomena ekonomi yang serupa.