添加国家因子后GAM模型绘图报错:美学属性y长度不匹配
GAM模型含国家因子后的绘图美学错误解决
问题描述
我在GAM模型中加入Country_Name作为因子来建模国家内部的关系(若此操作有误请指出),但绘图时抛出美学属性错误:
! Aesthetics must be either length 1 or the same as the data (480): y
现有代码与数据
模型代码
mod = gam(gdp_per_capita ~ s(fisheries_production_pc, k = 25, bs = 'cs') + as.factor(Country_Name), data = economy_df, family = gaussian(link = "log")) #predictions preds = predict(mod, type = 'response', se.fit = TRUE) #plot model plot = ggplot(economy_df, aes(y = gdp_per_capita, x = fisheries_production_pc)) + geom_point() + geom_line(aes(fisheries_production_pc, preds$fit), colour = 'red') + scale_x_log10()
数据片段
Country_Name year gdp_per_capita fisheries_production Albania 1997 717.3800 1110.80 Albania 1998 813.7894 2807.50 Albania 1999 1033.2425 3057.90 Albania 2000 1126.6833 3635.00 Albania 2001 1281.6598 3597.20 Albania 2002 1425.1242 4516.80 Bosnia 1997 982.8018 253.00 Bosnia 1998 1102.3907 254.00 Bosnia 1999 1251.7476 255.00 Bosnia 2000 1484.1761 255.00 Bosnia 2001 1544.6021 255.00 Croatia 1997 5312.3695 20551.49 Croatia 1998 5691.1095 27935.08 Croatia 1999 5246.9360 25222.19 Croatia 2000 4887.7137 27944.24 Croatia 2001 5412.9251 29019.12 Cyprus 1997 14234.2441 25788.00 Cyprus 1998 15092.8262 20482.00 Cyprus 1999 15287.9189 41060.00 Cyprus 2000 14388.3477 70223.00
错误原因
你猜的没错:加入国家因子后,模型的预测值是分国家的分组结果,但原绘图代码存在两个问题:
geom_line继承了全局aes中的y = gdp_per_capita,同时又在自己的aes里指定y = preds$fit,导致美学属性冲突;- 没有按
Country_Name分组,ggplot无法识别每个预测值对应的国家,线条绘制逻辑混乱。
另外注意:模型里用了fisheries_production_pc,但数据片段里只有fisheries_production,推测是笔误,后续代码默认你已经处理好这个变量。
修正后的绘图代码
第一步:绑定预测值到原数据框
先把预测值和原数据合并,确保每个观测对应自己的预测值,保留国家分组信息:
economy_df$pred_fit = preds$fit economy_df$pred_se = preds$se.fit
第二步:按国家分组绘制拟合线
因为模型给每个国家加了独立截距,所以需要按国家分组绘制拟合线,修正美学映射:
library(ggplot2) library(mgcv) # 基础绘图:点+分国家拟合线 plot = ggplot(economy_df, aes(x = fisheries_production_pc, y = gdp_per_capita)) + geom_point(aes(color = Country_Name), alpha = 0.6) + # 点按国家上色,方便区分 geom_line(aes(y = pred_fit, color = Country_Name), linewidth = 1) + # 按国家分组画拟合线 scale_x_log10() + labs(x = "人均渔业产量", y = "人均GDP", color = "国家") + theme_minimal() print(plot)
可选:添加95%置信区间
如果需要展示预测的不确定性,加上geom_ribbon:
# 带置信区间的绘图 plot = ggplot(economy_df, aes(x = fisheries_production_pc, y = gdp_per_capita)) + geom_point(aes(color = Country_Name), alpha = 0.6) + geom_ribbon(aes(ymin = pred_fit - 1.96*pred_se, ymax = pred_fit + 1.96*pred_se, fill = Country_Name), alpha = 0.2) + geom_line(aes(y = pred_fit, color = Country_Name), linewidth = 1) + scale_x_log10() + labs(x = "人均渔业产量", y = "人均GDP", color = "国家", fill = "国家") + theme_minimal() print(plot)
关于模型的小建议
你用as.factor(Country_Name)加入国家固定效应的方式没问题。如果国家数量较多,推荐改用随机效应建模,能减少自由度消耗,更符合国家间截距存在变异的假设:
mod = gam(gdp_per_capita ~ s(fisheries_production_pc, k = 25, bs = 'cs') + s(Country_Name, bs = 're'), data = economy_df, family = gaussian(link = "log"))
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

