簡體   English   中英

R(或任何語言)中偏態正態分布的非線性最小二乘回歸

[英]Nonlinear least squares regression of skewed normal distribution in R (or any language)

第一次海報。 如果我使用不當的禮儀或詞匯,請提前道歉。

我有來自 USGS 河流調查的化學濃度 (y) 與時間 (x) 的時間序列數據。 它表現出我想通過非線性最小二乘回歸 model 的偏態正態分布。 我能夠為數據擬合正態分布曲線,但似乎無法將“偏度”納入 model。

我從這里的Whuber給出的答案得出了我的正態分布擬合......線性回歸最佳多項式(或更好的使用方法)?

我的數據和代碼...

y <- c(0.532431978850729, 0.609737363640599, 0.651964078008195, 0.657368066358271, 
0.741496240155044, 0.565435828629966, 0.703655525439792, 0.718855614453251, 
0.838983191559565, 0.743767469276213, 0.860155614137561, 0.81923941209205, 
1.07899884812998, 0.950877380129941, 1.01284743983765, 1.11717867112622, 
1.08452873942528, 1.14640319037414, 1.35601176845714, 1.55587090166098, 
1.81936731953165, 1.79952819117948, 2.27965075864338, 2.92158756334143, 
3.28092981974249, 1.09884083379528, 4.52126319475028, 5.50589160306292, 
6.48951979830975, 7.61196542128105, 9.56700470248019, 11.0814901164772, 
13.3072954022821, 13.8519364143597, 11.4108376964234, 8.72143939873907, 
5.12221325838613, 2.58106436004881, 1.0642701141608, 0.44945378376047, 
0.474569233285229, 0.128299654944011, 0.432876244482592, 0.445456125461339, 
0.435530646939433, 0.337503495863836, 0.456525976632425, 0.35851011819921, 
0.525854215793115, 0.381206935673774, 0.548351975353343, 0.365384673834335, 
0.418990479166088, 0.50039125911365, 0.490696977485334, 0.376809405620949, 
0.484559448760701, 0.569111550743562, 0.439671715276438, 0.353621820313257, 
0.444241243031233, 0.415197754444015, 0.474852839357701, 0.462144150397257, 
0.535339727332139, 0.480714031175711)

#creating an arbitrary vector to represent time
x <- seq(1,length(y), by=1)

#model of normal distribution 
f <- function(x, theta)  { 
  m <- theta[1]; s <- theta[2]; a <- theta[3]; b <- theta[4];
  a*exp(-0.5*((x-m)/s)^2) + b
}

# Estimate some starting values.
m.0 <- x[which.max(y)]; s.0 <- (max(x)-min(x))/4; b.0 <- min(y); a.0 <- (max(y)-min(y))

# Do the fit.  (It takes no time at all.)
fit <- nls(y ~ f(x,c(m,s,a,b)), data.frame(x,y), start=list(m=m.0, s=s.0, a=a.0, b=b.0))

# Display the estimated location of the peak and its SE.
summary(fit)$parameters["m", 1:2]

par(mfrow=c(1,1))
plot(c(x,0),c(y,f(coef(fit)["m"],coef(fit))), main="Data", type="n",
     xlab="Time", ylab="Concentration")
curve(f(x, coef(fit)), add=TRUE, col="Red", lwd=2)
points(x,y, pch=19)

那么,關於如何調整 model 以適應偏斜有什么建議嗎?

干杯,傑米

數據是河流水樣中某些化合物的濃度與時間的關系,不是嗎? 如果我 plot y vs x,假設樣本是在固定的時間間隔采集的,我看到一個濃度峰值,因此時間依賴性似乎是某種物理和/或化學現象,可以建模為 y = f(b, x) + e,其中f是化學/物理現象參數b的function,x代表時間。 項 e 是隨機誤差,在化學中通常獨立測量樣品,因此 e ~ N(0, s^2)。 然后你用nls擬合 f(b, x) 。

您可以使用廣義添加劑 model (GAM) 嗎? GAM 功能強大且靈活,但很難解釋 model 系數。 所以決定將取決於你的目的。 如果目的是評估趨勢,或者目的是預測濃度(在已知時間范圍內),那么 GAM 可能是一個不錯的選擇。

library(mgcv)
library(ggplot2)

dat <- data.frame(x = 1:length(y), y = y)

fit_gam <- gam(y ~ s(x, k = 20), data = dat) 

ggplot(dat, aes(x = x, y = y)) +
  geom_point() +
  geom_line(data = data.frame(x = x, y = fit_gam$fitted.values),
            color = "red") +
  ggtitle("Data") +
  xlab("Cocentration") +
  ylab("Time") +
  theme_bw() +
  theme(panel.grid = element_blank())

在此處輸入圖像描述

以下是應用stat_smooth以適應相同 GAM model 的另一個選項。

ggplot(dat, aes(x = x, y = y)) +
  geom_point() +
  stat_smooth(method = "gam", formula = y ~ s(x, bs = "tp", k = 20)) +
  ggtitle("Data") +
  xlab("Cocentration") +
  ylab("Time") +
  theme_bw() +
  theme(panel.grid = element_blank())

在此處輸入圖像描述

我與一位在 python 中的奇才的伙伴交談,他幫助我構建了正確的偏態正態分布方程。 我在下面發布了 R 腳本。

我想要做的是用右偏分布 model 替換正態分布 model。 吸引我的不是腳本編寫,而是我編寫右偏分布的一般方程的能力(我的伙伴也是數學奇才)。

我對 www 豎起大拇指,因為出於所有密集目的,他們回答了我的問題。 我喜歡他們也使用 GAM 采用不同的方法,盡管我對 model 產生的系數感興趣。

我的下一個計划是整合 model 曲線下的面積,以及置信區間曲線下的面積。

stackoverflow 的第一次體驗很好。 謝謝你們。

f <- function(x, theta)  { 
  m <- theta[1]; s <- theta[2]; a <- theta[3]; b <- theta[4]; k <- theta[5]
  a*exp(k*((x - m))/s - sqrt(((x - m))/s*((x - m))/s+1)) + b
}

# Estimate some starting values.
m.0 <- x[which.max(y)]; s.0 <- (max(x)-min(x))/4; b.0 <- min(y); a.0 <- (max(y)-min(y)); k.0 <- -0.5

# Do the fit.  (It takes no time at all.)
fit <- nls(y ~ f(x,c(m,s,a,b, k)), data.frame(x,y), start=list(m=m.0, s=s.0, a=a.0, b=b.0, k=k.0))

# Display the estimated location of the peak and its SE.
summary(fit)$parameters["m", 1:2]

par(mfrow=c(1,1))
plot(c(x,0),c(y,f(coef(fit)["m"],coef(fit))), main="Data", type="n",
     xlab="Time", ylab="Concentration")
curve(f(x, coef(fit)), add=TRUE, col="Red", lwd=2)
points(x,y, pch=19)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM