如何将公式传递给具有权重的 lm 对象?

How to pass formulae to lm objects with weights?

当公式向上一级时,为什么我无法将公式传递给具有权重的 lm 对象?

n <- 100
x <- seq(n)
y <- x + rnorm(n)
dat <- data.frame(y,x)   

## Success With OLS when passing formula
form <- y~x
llls <- sapply( seq(x), function(i){
    reg <- lm(form, data=dat)
})

## Success with WLS when not passing weights
llls <- sapply( seq(x), function(i){
    weight_i <- dnorm( (x[i]-x)/2)
    reg <- lm(y~x, data=dat, weights=weight_i)
})

## Failure with WLS when passing formula 
form <- y~x
llls <- sapply( seq(x), function(i){
    weight_i <- dnorm( (x[i]-x)/2)
    reg <- lm(form, data=dat, weights=weight_i)
})

R 版本 4.0.2

问题是 lm 试图在 dat 或编写公式的环境中找到 weights_i。简单的解决方案是在 dat 中创建权重作为临时列。这可以防止将变量写入全局环境。

form <- y~x
sapply( seq(x), function(i){
    dat$weight_i <- dnorm( (x[i]-x)/2)
    reg <- lm(form, data=dat, weights=weight_i)
})
#>               [,1]        [,2]        [,3]        [,4]        [,5]       
#> coefficients  Numeric,2   Numeric,2   Numeric,2   Numeric,2   Numeric,2  
#> residuals     Numeric,100 Numeric,100 Numeric,100 Numeric,100 Numeric,100
#> fitted.values Numeric,100 Numeric,100 Numeric,100 Numeric,100 Numeric,100
#> effects       Numeric,78  Numeric,79  Numeric,80  Numeric,81  Numeric,82 
#> weights       Numeric,100 Numeric,100 Numeric,100 Numeric,100 Numeric,100
#> rank          2           2           2           2           2          
#> assign        Integer,2   Integer,2   Integer,2   Integer,2   Integer,2  
#> qr            List,5      List,5      List,5      List,5      List,5     
#> df.residual   76          77          78          79          80         
#> xlevels       List,0      List,0      List,0      List,0      List,0     
#>               [,6]        [,7]        [,8]        [,9]        [,10]      
#> coefficients  Numeric,2   Numeric,2   Numeric,2   Numeric,2   Numeric,2  
#> residuals     Numeric,100 Numeric,100 Numeric,100 Numeric,100 Numeric,100
#> fitted.values Numeric,100 Numeric,100 Numeric,100 Numeric,100 Numeric,100
#> effects       Numeric,83  Numeric,84  Numeric,85  Numeric,86  Numeric,87 
#> weights       Numeric,100 Numeric,100 Numeric,100 Numeric,100 Numeric,100
#> rank          2           2           2           2           2          
#> 
#> ...etc

好消息是,这不会对 dat 或您的调用环境造成任何永久性更改:

head(dat)
#>           y x
#> 1 0.6125909 1
#> 2 1.5101739 2
#> 3 1.9893877 3
#> 4 4.6632718 4
#> 5 6.1132429 5
#> 6 5.2509379 6

您还可以制作一个包含所有参数的列表并使用 do.call()

form <- y~x
llls <- sapply( seq(x), function(i){
  l <- list(formula=form, 
            data = dat, 
            weights = weight_i <- dnorm( (x[i]-x)/2)
        )
  reg <- do.call(lm, l)
})