在mgcv多项GAM中使用权重:鱼类洄游阶段比例建模问询
Hey there! Great question—using mgcv to fit multinomial GAMs with proportional weights is totally feasible, and I’ll break down exactly how to set this up correctly for your fry/parr/smolt stage data.
First, Let’s Clarify the Data Structure
Unlike nnet::multinom which often works with wide-format data (one column per stage), mgcv’s multinomial GAM expects long-format data. That means each row should represent a single stage observation for a given day, with columns for:
- Your predictor variables (e.g., water temperature, day of year, river flow)
- A factor variable for the stage (
fry,parr,smolt) - A weight column tied to the observed proportion for that stage on the day (typically the count of individuals in that stage, or the total daily count—more on this below)
Step 1: Prepare Your Data
Let’s use a simulated example to mirror your scenario. Suppose you have daily counts for each stage and some covariates:
library(mgcv) set.seed(123) # For reproducibility # Simulate 100 days of data n_days <- 100 days <- 1:n_days temp <- rnorm(n_days, mean = 12, sd = 2) # Water temperature covariate # Generate true proportional probabilities for each stage p_fry <- plogis(0.08*days - 0.15*temp) p_parr <- plogis(-0.05*days + 0.1*temp) p_smolt <- 1 - p_fry - p_parr # Total daily observations (varying per day) total_daily <- sample(60:200, n_days, replace = TRUE) # Simulate counts for each stage fry_counts <- rbinom(n_days, size = total_daily, prob = p_fry) parr_counts <- rbinom(n_days, size = total_daily - fry_counts, prob = p_parr/(p_parr + p_smolt)) smolt_counts <- total_daily - fry_counts - parr_counts # Reshape to long format dat_long <- data.frame( day = rep(days, 3), temp = rep(temp, 3), stage = factor(rep(c("fry", "parr", "smolt"), each = n_days)), count = c(fry_counts, parr_counts, smolt_counts), total_daily = rep(total_daily, 3) # Optional: total daily counts for weighting )
Step 2: Fit the Weighted Multinomial GAM
The key here is using the weights argument in mgcv::gam() alongside the multinom() family. The weights should reflect the reliability of each stage’s proportion on a given day:
- If you want to weight by the number of individuals observed in the stage, use the
countcolumn (this gives more weight to days where you have more observations for that stage) - If you want to weight by the total daily observations (giving equal weight to each day, regardless of stage-specific counts), use the
total_dailycolumn
Here’s how to fit the model with stage-specific counts as weights:
# Fit the multinomial GAM with splines for day and temperature mod <- gam( formula = stage ~ s(day) + s(temp), data = dat_long, family = multinom(), weights = count, # This is where your regression weights go! method = "REML" # Recommended for smoothness selection ) # Check model summary summary(mod) # Run diagnostic checks gam.check(mod)
Key Notes to Avoid Pitfalls
- Reference Category: By default,
multinom()uses the first level of yourstagefactor as the reference. To change this (e.g., setsmoltas reference), usedat_long$stage <- relevel(dat_long$stage, ref = "smolt")before fitting. - Weight Interpretation: The weights in this context act like case weights—they scale the contribution of each observation to the log-likelihood. Using stage counts makes sense because days with more individuals in a stage have more reliable proportion estimates.
- Predictions: To get predicted probabilities for each stage, use
predict(mod, newdata = your_new_data, type = "response"). This will return a matrix where each column is the predicted probability for a stage.
Quick Comparison to nnet::multinom
The main difference is that mgcv lets you easily add smooth spline terms (like s(day)) to model non-linear relationships between covariates and stage proportions, whereas nnet::multinom is limited to linear terms. The weighting setup is analogous, but the data format switch (wide → long) is critical for mgcv.
内容的提问来源于stack exchange,提问作者Hugh Sturrock

