如何将多元GAM模型的y轴从平滑值更改为实际值?

时间:2019-05-28 21:29:18

标签: r predict gam mgcv

我正在使用多元GAM模型来了解有关多个区域的雾趋势的更多信息。雾是由能见度低于某个阈值(<400米)确定的。我们的GAM模型用于确定能见度对一系列气象变量的响应。

但是,我现在面临的挑战是,我真的希望y轴成为实际的可见性观测值,而不是居中平滑。有趣的是,相对于该位置的平均可见性,协变量如何影响可见性,但是对于平均可见性不同的多个位置(因此,0点能见度提高或降低的可比性意义不大)。

为了比较多个位置的结果,我尝试进行y轴实际可见性观察,然后将一条线放在我们有兴趣查看的可见性阈值(400 m) 评估低于该阈值的预测变量值是什么样的(例如,温度与低于400 m的能见度相关联)。

一般来说,我还是GAM和R的初学者,但到目前为止,我已经找到了一些有用的内容。

到目前为止有用的东西:

尝试1.如何为模型中的每个变量提取gam fit Extracting data used to make a smooth plot in mgcv

尝试2.如何使用预测函数重建单变量模型 http://zevross.com/blog/2014/09/15/recreate-the-gam-partial-regression-smooth-plots-from-r-package-mgcv-with-a-little-style/

尝试3.如何使用“拟合”获得看起来像能见度观察的y轴的某种外观-尽管我认为这不是 正确的方法,因为我没有考虑拦截 http://gsp.humboldt.edu/OLM/R/05_03_GAM.html

模拟数据

install.packages("mgcv") #for gam package
require(mgcv)
install.packages("pspline")
require(pspline)


#simulated GAM data for example
dataSet <- gamSim(eg=1,n=400,dist="normal",scale=2)
visibility <- dataSet[[1]]
temperature <- dataSet[[2]]
dewpoint <- dataSet[[3]]
windspeed <- dataSet[[4]]


#Univariable GAM model
gamobj <- gam(visibility ~  s(dewpoint))
plot(gamobj, scale=0, page=1, shade = TRUE, all.terms=TRUE, cex.axis=1.5, cex.lab=1.5, main="Univariable Model: Dew Point")
summary(gamobj)
AIC(gamobj)
abline(h=0)

露点单变量模型 https://imgur.com/1uzP34F

ATTEMPT 2-用单变量模型预测函数,但没有改变y轴

#dummy var that spans length of original covariate
maxDP <-max(dewpoint)
minDP <-min(dewpoint)
DPtrial.seq <-seq(minDP,maxDP,length=3071)
DPtrial.seq <-data.frame(dewpoint=DPtrial.seq)

#predict only the DP term 
preds <- predict(gamobj, type="terms", newdata=DPtrial.seq, se.fit=TRUE)

#determine confidence intervals
DPplot <-DPtrial.seq$dewpoint
fit <-preds$fit
fit.up95 <-fit-1.96*preds$se.fit
fit.low95 <-fit+1.96*preds$se.fit

#plot
plot(DPplot, fit, lwd=3,
 main="Reconstructed Dew Point Covariate Plot")

#plot confident intervals
polygon(c(DPplot, rev(DPplot)), 
    c(fit.low95,rev(fit.up95)), col="grey",
    border=NA)

lines(DPplot, fit,  lwd=2)
rug(dewpoint) 

重构露点协变量图 https://imgur.com/VS8QEcp

ATTEMPT 3-使用“ fitted”更改了y轴,但没有考虑拦截

plot(dewpoint,fitted(gamobj), main="Fitted Response of Y (Visibility) Plotted Against Dew Point")
abline(h=mean(visibility))
rug(dewpoint)

针对露点https://imgur.com/RO0q6Vw绘制的Y的拟合响应

最终,我需要一条水平线,在这里我可以研究相对于400米的预测变量,而不仅仅是响应变量的均值。这样,在平均可见度不同的多个站点中,它是可比的。最重要的是,它必须用于多个协变量!

Gavin Simpson在几篇文章中已经解释了该方法,但是不幸的是,当我使用预测函数时,我真的不明白如何保持其他协变量的平均值不变。

Changing the Y axis of default plot.gam graphs

对此方法进行更深入的说明将非常有帮助!

1 个答案:

答案 0 :(得分:0)

我不确定这将有多大帮助,因为您的问号比我们通常在SO上要开放的要开放一些,但是,到了。

首先,我认为考虑对响应变量建模是有帮助的,我认为当前是可见性。这将是一个连续变量,以0为界(也许数据永远不会达到零?),因此建议将数据建模为有条件分布

  • 伽玛(family = Gamma(link = 'log'))的可见度永远不会为零。
  • Tweedie(family = tw())用于包含零的数据。

另一种方法是模拟雾的发生;如果将其定义为可见度<400m的事件,则可以将所有观测值转换为0/1值(如果是大雾事件)。然后,您可以使用family = binomial()将数据建模为有条件分布的Bernoulli。

决定采用建模方法后,我们需要对响应进行建模。这应该使用多元回归类型的方法来完成,并且GAM包括多个预测变量。通过这种方式,您可以估算每个潜在预测变量对响应的影响,同时控制其他预测变量的影响。如果您一次只使用一个预测变量,例如说dewpoint,则该变量很可能“解释”数据的变化,这可能是由于另一个预测变量windspeed引起的,而您不会不知道。

此外,您可能想要控制的预测变量之间可能存在交互,这只能在

中完成

然后,为了最终解决问题的症结,已经为“解释”可见性安装了多预测器模型,您将需要从模型中预测可能的条件集。要查看在其他预测变量有影响的模型中可见性随dewpoint的变化,您需要将其他变量固定为一些合理的值;一种选择是将其设置为平均值(或在任何因子预测变量的情况下为模态值),或其他表示该变量通常值的其他值。您必须使用您的领域知识。

如果模型中存在交互,则需要更改交互中的两个变量,同时将所有其他变量固定为某个值。

假设您没有互动,并且对dewpoint感兴趣,但是该模型还包含windspeed。可从拟合模型的cmX组件中找到用于拟合模型的值的平均风速。您可以只从观察到的windpseed值中计算出该值,或将其设置为您要使用的某个已知数字。用m表示拟合,用df表示包含数据的数据框,然后我们可以创建新数据以在dewpoint范围内进行预测,同时按住{{1 }}。

windspeed

那你就可以做

mn.windspd <- m$cmX['windspeed']
## or
mn.windspd <- with(df, mean(windspeed))
## or set it some some value
mn.windspd <- 10 # say

然后,您可以使用它来预测拟合模型:

preddata <- with(df,
                 expand.grid(dewpoint = seq(min(dewpoint),
                                            max(dewpoint),
                                            length = 300),
                             windspeed = mn.windspd))

现在,我们希望将这些预测恢复到响应规模,并且我们需要一个置信区间,因此我们必须先创建该区间,然后再进行逆变换:

pred <- predict(m, newdata = preddata, type = "link", se.fit = TRUE)
pred <- as.data.frame(pred)

现在,您可以可视化ilink <- family(m)$linkinv pred <- transform(pred, Fitted = ilink(fit), Upper = ilink(fit + (2 * se.fit)), Lower = ilink(fit - (2 * se.fit)), dewpoint = preddata = dewpoint) 对响应的影响,同时保持dewpoint固定。

在您的情况下,您还必须将其扩展为也保持windspeed不变,但这可以通过相同的方式完成

temperature

,然后按照上述步骤进行预测。

对于一个或两个变量,我在 gratia 包中有一个函数mn.windspd <- m$cmX['windspeed'] mn.temp <- m$cmX['temperature'] preddata <- with(df, expand.grid(dewpoint = seq(min(dewpoint), max(dewpoint), length = 300), windspeed = mn.windspd, temperature = mn.temp)) ,它将为您完成上述data_slice()的工作,因此您不必指定其他协变量的平均值:

expand.grid()

从技术上讲,这将找到最接近中值的数据值(对于协变量不变)。如果您想要手段,那么

preddata <- data_slice(m, 'dewpoint', n = 300)

如果您有互动,例如说fixdf <- data.frame(windspeed = mn.windspd, temperature = mn.temp) preddata <- data_slice(m, 'dewpoint', data = fixdf, n = 300) dewpoint之间,则需要改变两个变量。使用windspeed再次很容易:

expand.grid()

这将创建一个100 x 100的协变量值网格,以在保持温度恒定的同时进行预测。

对于mn.temp <- m$cmX['temperature'] preddata <- with(df, expand.grid(dewpoint = seq(min(dewpoint), max(dewpoint), length = 100), windspeed = seq(min(windspeed), max(windspeed), length = 300), temperature = mn.temp)) ,您需要执行以下操作:

data_slice()

将此模式扩展到您想要变化的更多协变量,也很容易遵循fixdf <- data.frame(temperature = mn.temp) preddata <- data_slice(m, 'dewpoint', 'windpseed', data = fixdf, n = 300) 遵循此模式;我尚未实现expand.grid()中两个以上的变量。