使用从 tidyr 收集改变了我的回归结果

Using gather from tidyr changes my regression results

当我运行下面的代码时,一切都按预期工作

# install.packages("dynlm")
# install.packages("tidyr")
require(dynlm)
require(tidyr)


Time <- 1950:1993

Y <- c(5820, 5843, 5917, 6054, 6099, 6365, 6440, 6465, 6449, 6658,  6698, 6740, 6931, 
       7089, 7384, 7703, 8005, 8163, 8506, 8737, 8842, 9022, 9425,  9752, 9602, 9711, 
       10121, 10425, 10744, 10876, 10746, 10770, 10782, 11179, 11617, 12015, 12336, 
       12568, 12903, 13029, 13093, 12899, 13110, 13391)

X <- c(6284, 6390, 6476, 6640, 6628, 6879, 7080, 7114, 7113, 7256, 7264, 7382, 7583, 7718,  
       8140, 8508, 8822, 9114, 9399, 9606, 9875, 10111, 10414, 11013, 10832, 10906, 11192, 
       11406, 11851, 12039, 12005, 12156, 12146, 12349, 13029, 13258, 13552, 13545, 13890, 
       14005, 14101, 14003, 14279, 14341)

data <- data.frame(Time, Y, X)

data_ts <- ts(data, start = 1950, end = 1993, frequency = 1)

Modell <- dynlm(log(Y) ~ log(X) + log(L(X)) + log(L(X, 2)) + log(L(X, 3)) 
                     + log(L(X, 4)) + log(L(X, 5)), data = data_ts)
summary(Modell)

我在这种情况下的摘要输出是这样的

...        
              Estimate  Std. Error t value Pr(>|t|)    
(Intercept)  -0.059109   0.091926  -0.643    0.525    
log(X)        0.883020   0.145754   6.058 9.17e-07 ***
log(L(X))     0.004167   0.211420   0.020    0.984    
log(L(X, 2)) -0.092880   0.207026  -0.449    0.657    
log(L(X, 3)) -0.012016   0.210395  -0.057    0.955    
log(L(X, 4))  0.200596   0.212370   0.945    0.352    
log(L(X, 5))  0.014497   0.144103   0.101    0.920 
...

现在,当我使用 gather() 为一些地块定义新的数据框时

data_tidyr <- gather(data, "Key", "Value", -Time)

并重新 运行 上面的代码没有改变任何其他东西我得到这个摘要:

              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -0.05669    0.07546  -0.751    0.457    
log(X)        0.82128    0.13486   6.090 3.53e-07 ***
log(L(X))     0.17484    0.13365   1.308    0.198    
log(L(X, 2))       NA         NA      NA       NA    
log(L(X, 3))       NA         NA      NA       NA    
log(L(X, 4))       NA         NA      NA       NA    
log(L(X, 5))       NA         NA      NA       NA 

我对这种行为感到困惑,因为收集操作(定义一个新的数据框,将列收集到行中)与我用于 运行 我的回归的数据集无关(至少这个是我的印象)。 不知何故使用 gather() 改变了计算的完成方式,但我看不到如何。非常感谢您的帮助!

一些数字:

更新

好的,感谢您到目前为止的所有回答和评论,但问题仍然存在:环境中发生了什么?我想知道为什么以及如何发生这种情况。对我来说,这是一件严肃的事情,因为据我所知,避免一个函数调用对其他函数的非预期副作用恰恰是像 R 这样的函数式语言试图实现的目标。现在,除非我在这里遗漏了什么,否则这种行为似乎与那个意图不一致。

当我 运行 你在 R 3.1.3 中的第一个代码块时,我得到了你显示的结果作为你的第二组结果:

(R 版本 3.1.3,dynlm 版本 .3-3)。

Time series regression with "ts" data:
Start = 1951, End = 1993

Call:
dynlm(formula = log(Y) ~ log(X) + log(L(X)) + log(L(X, 2)) + 
    log(L(X, 3)) + log(L(X, 4)) + log(L(X, 5)), data = data_ts)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.030753 -0.006364  0.001321  0.007939  0.025982 

Coefficients: (4 not defined because of singularities)
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -0.05669    0.07546  -0.751    0.457    
log(X)        0.82128    0.13486   6.090 3.53e-07 ***
log(L(X))     0.17484    0.13365   1.308    0.198    
log(L(X, 2))       NA         NA      NA       NA    
log(L(X, 3))       NA         NA      NA       NA    
log(L(X, 4))       NA         NA      NA       NA    
log(L(X, 5))       NA         NA      NA       NA    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.01419 on 40 degrees of freedom
Multiple R-squared:  0.9974,    Adjusted R-squared:  0.9972 
F-statistic:  7578 on 2 and 40 DF,  p-value: < 2.2e-16

然而,当我更新到 R 3.2.0 时,我重复了你最初得到的结果,但后来又回到了总是得到第二个结果的状态。

现在,从您以后的评论中,您也始终如一地获得第二个结果。 所以我认为一定是代码中某个时候出现了错别字,或者第一次在空环境中运行时出现了一些问题。

基于这个假设,我完全关闭了 RStudio,重新启动并 运行 第一个代码块。 这样我又得到了你的初步结果。

所以我认为你的问题的答案必须是环境中发生了一些奇怪的事情。

我阅读了 dynlm 的文档,有几个地方的默认值(如果它们起作用的话)可能会导致差异。例如,如果未指定数据,它将从环境中获取变量。它将使用时间序列对象或数据框。在您的情况下,您同时拥有环境(数据和 data_ts)。如果您注意到上面的摘要输出,它会显示 Time series regression with "ts" data:,这意味着它是 运行 一个 ts 对象。当我得到另一个结果时(没有 NA,你的第一个结果)它说 Time series regression with "numeric" data: 在这种情况下它是 运行 on data 这是一个数据帧或直接 X 和 Y。所以我认为这一定是差异的根源。我不确定为什么 data_ts 明确命名时会发生这种情况。

此意外更改的根本原因是 dplyrdplyr,而不是 tidyr)更改了 lag 函数的默认方法。 gather 函数调用 dplyr::select_vars,它通过命名空间加载 dplyr 并覆盖 lag.default

当您在公式中使用 L 时,dynlm 函数会在内部调用 lag。然后方法调度找到 lag.default。当通过命名空间加载 dplyr 时(甚至不需要附加),会找到 dplyr 中的 lag.default

这两个滞后函数根本不同。在新的 R 会话中,您会发现以下差异:

lag(1:3, 1)
## [1] 1 2 3
## attr(,"tsp")
## [1] 0 2 1
invisible(dplyr::mutate) # side effect: loads dplyr via namespace...
lag(1:3, 1)
## [1] NA  1  2

因此解决方案相当简单。只需自己覆盖 lag.default 函数即可。

lag.default <- stats:::lag.default
dynlm(log(Y) ~ log(X) + log(L(X)) + log(L(X, 2)), data = data_ts)

## Time series regression with "ts" data:
##   Start = 1952, End = 1993
## 
## Call:
##   dynlm(formula = log(Y) ~ log(X) + log(L(X)) + log(L(X, 2)), data = data_ts)
## 
## Coefficients:
##   (Intercept)        log(X)     log(L(X))  log(L(X, 2))  
## -0.05476       0.83870       0.01818       0.13928      

lag.default <- dplyr:::lag.default
dynlm(log(Y) ~ log(X) + log(L(X)) + log(L(X, 2)), data = data_ts)

## Time series regression with "ts" data:
## Start = 1951, End = 1993
## 
## Call:
## dynlm(formula = log(Y) ~ log(X) + log(L(X)) + log(L(X, 2)), data = data_ts)
## 
## Coefficients:
##  (Intercept)        log(X)     log(L(X))  log(L(X, 2))  
##     -0.05669       0.82128       0.17484            NA  

lag.default <- stats:::lag.default
dynlm(log(Y) ~ log(X) + log(L(X)) + log(L(X, 2)), data = data_ts)

## Time series regression with "ts" data:
##   Start = 1952, End = 1993
## 
## Call:
##   dynlm(formula = log(Y) ~ log(X) + log(L(X)) + log(L(X, 2)), data = data_ts)
## 
## Coefficients:
##   (Intercept)        log(X)     log(L(X))  log(L(X, 2))  
## -0.05476       0.83870       0.01818       0.13928