在gam函数中出现错误,提示'names'属性的长度必须与向量长度相同。

10

我正在使用mgcv包来根据一些环境协变量建模臭氧污染浓度。该模型的形式为:

model1 <- gam(O3 ~ s(X, Y, bs = "tp", k = 10) + wd + s(date, bs = "cc", k = 100) + district,
              data = mydata, family = gaussian(link ="log"),
              na.action = "na.omit", method = "REML")

这里是协变量的结构:

> str(mydata)
'data.frame': 7100 obs. of  286 variables:
 $ date            : Date, format: "2016-01-01" "2016-01-01" "2016-01-01" ...
 $ O3              : num  0.0141 0.0149 0.0102 0.0159 0.0186 ...
 $ district        : Factor w/ 10 levels "bc","bh","dl",..: 1 8 7 8 2 6 4 4 10 2 ...
 $ wd              : Factor w/ 16 levels "E","ENE","ESE",..: 13 13 13 13 13 2 9 9 11 13 ...
 $ X               : num  0.389 0.365 1 0.44 0.892 ...
 $ Y               : num  0.311 0.204 0.426 0.223 0.162 ...

我在R中遇到了一个问题:

错误信息:'names'属性[1]的长度必须与向量[0]的长度相同。

我尝试通过从公式中删除s(date, bs = "cc", k = 100)这个部分来找出问题所在,这样可以解决问题。看起来是日期字段出了问题。

我不确定该如何修复这个问题,希望能得到任何建议!


看起来你需要将日期类转换为数字。(附注:我经常看到周期样条用于月份/周数等,而不是原始日期) - user20650
2
给出的答案已经足够了,但我要补充一点,当我使用一个字符变量来处理因子时,我遇到了同样的错误,但我没有正式将其定义为因子。通过将其转换为 "mutate(var1 = as.factor(var.1))",问题得以解决。 - Kodiakflds
此Stack Exchange答案链接提供给像我这样的人,他们可能会忘记将所有字符变量转换为因子。 - Corey N.
1个回答

11

date变量不会自动转换为数字变量,需要您自己完成。我通常会按照以下方式处理这样的信息:

变量 date 不会自动转换为数字类型,您需要手动进行转换。我通常按照以下方式处理此类信息:

mydata <- transform(mydata, ndate = as.numeric(date),
                    nyear  = as.numeric(format(date, '%Y')),
                    nmonth = as.numeric(format(date, '%m')),
                    doy    = as.numeric(format(date, '%j')))

那么我可以选择以多种方式对时间因素进行建模:

  1. 基于ndatenyear趋势,使用非循环样条;或者
  2. 基于nmonthdoy(一年中的第几天)的循环模式;或者
  3. 趋势和循环模式的组合

从你的问题中不清楚你的数据是否仅限于单一年份。如果数据跨越多年,则不能仅在ndate变量上使用循环样条。你需要使用一个非常复杂的标准样条(选项1),或者包括两个样条,一个用于年间部分,另一个用于年内部分(选项3)。

如果你的数据跨越多年,那么我会将模型设置为:

O3 ~ s(X, Y, bs = "tp", k = 10) + wd + s(doy, bs = 'cc', k = 20) +
     s(ndate, bs = "tp", k = 50) + district

或许 s(nyear, .... ) 可以代替 s(ndate, .... ),达到相同的效果。

这种时间分解的方法非常有用,因为你可以通过两个简单且预测准确的平滑函数更好地拟合数据序列,而不是使用一个更复杂的平滑函数。它还可以让你测试年度内部和年度间的影响。

如果你需要季节周期随着趋势变化而变化,那么张量积是有帮助的:

O3 ~ s(X, Y, bs = "tp", k = 10) + wd +
     te(doy, ndate, bs = c('cc','tp'), k = c(20,50)) + district

对于循环样条,你可能还想设置knots参数,特别是如果你的数据不完全涵盖一整年中的所有日子等时间范围。 对于doy,我建议使用 knots = list(doy = c(0.5, 366.5)),因为这可以使12月31日和1月1日具有略微不同的估计值。对于nmonth来说,这更为重要,否则12月和1月将获得相同的拟合值。 我使用:knots = list(nmonth = c(0.5, 12.5))

这里的思路是112分别表示各自月份的中间位置,而0.512.5则表示第一个和最后一个月的开头和结尾,我们可能希望它们是相同的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接