【问题标题】:Applying lags to data without loop将滞后应用于没有循环的数据
【发布时间】:2021-07-03 04:09:59
【问题描述】:

让我们考虑以下数据集:

library(plm)
data("EmplUK", package = 'plm')
df <- EmplUK[1:6]
head(df)
> head(df)
  firm year sector   emp    wage capital
1    1 1977      7 5.041 13.1516  0.5894
2    1 1978      7 5.600 12.3018  0.6318
3    1 1979      7 5.015 12.8395  0.6771
4    1 1980      7 4.715 13.8039  0.6171
5    1 1981      7 4.093 14.2897  0.5076
6    1 1982      7 3.166 14.8681  0.4229

如您所见,它是基本面板数据。现在我想对这个数据集应用滞后,但我当然不想对公司和年份应用滞后。

现在让我们将滞后向量定义为lags &lt;- c(2,1,3,0)。这意味着:

(1) 扇区的两个滞后(数据帧中的第三个变量)

(2) emp 有一个滞后(数据框中的第四个变量)

(3) 工资的三个滞后(数据框中的第五个变量)

(4) 资本零滞后(数据框中的第六个变量)

当然,对于面板数据的约定,必须应用滞后 - 即包括每个周期开始时的滞后。

我的解决方案

for (i in seq_len(length(lags))) {
  # Filter our data and apply lags for each time period
  df <- df %>%
    dplyr::group_by_at(1) %>%
    # Take only those observations which amount 
    # is bigger than maximum number of lags
    dplyr::filter(n() > max(lags)) %>%
    dplyr::mutate(dplyr::across(
      colnames(df)[i + 2], dplyr::lag,
      n = lags[i], default = NA
    ))
}

> head(df)

> head(df)
# A tibble: 6 x 6
# Groups:   firm [1]
   firm  year sector   emp  wage capital
  <dbl> <dbl>  <dbl> <dbl> <dbl>   <dbl>
1     1  1977     NA NA     NA     0.589
2     1  1978     NA  5.04  NA     0.632
3     1  1979      7  5.60  NA     0.677
4     1  1980      7  5.01  13.2   0.617
5     1  1981      7  4.72  12.3   0.508
6     1  1982      7  4.09  12.8   0.423 

但是,尽管它可以工作,但我发现它很不方便 - 我使用循环来完成它,但我确定在那里没有必要。你能帮我重写我做过但没有循环的代码吗?

【问题讨论】:

    标签: r dataframe loops dplyr


    【解决方案1】:

    试着这样做

    library(tidyverse)
    data("EmplUK", package = 'plm')
    df <- EmplUK[1:6]
    
    Lag <- c(0, 0, 2, 1 ,3, 0)
    df_split <- group_split(df, firm)
    
    map_df(df_split, ~map2_df(.x, Lag, ~lag(.x, n = .y)))
    #> # A tibble: 1,031 x 6
    #>     firm  year sector   emp  wage capital
    #>    <dbl> <dbl>  <dbl> <dbl> <dbl>   <dbl>
    #>  1     1  1977     NA NA     NA     0.589
    #>  2     1  1978     NA  5.04  NA     0.632
    #>  3     1  1979      7  5.60  NA     0.677
    #>  4     1  1980      7  5.01  13.2   0.617
    #>  5     1  1981      7  4.72  12.3   0.508
    #>  6     1  1982      7  4.09  12.8   0.423
    #>  7     1  1983      7  3.17  13.8   0.392
    #>  8     2  1977     NA NA     NA    16.9  
    #>  9     2  1978     NA 71.3   NA    17.2  
    #> 10     2  1979      7 70.6   NA    17.5  
    #> # ... with 1,021 more rows
    

    reprex package (v2.0.0) 于 2021-04-07 创建

    【讨论】:

    • 感谢您的回答!我对您的解决方案的问题是,它只是在第一次观察中增加了滞后,而在面板数据中,我们希望在每个时期的开始都有滞后。
    【解决方案2】:

    一种稍微复杂的方法是在函数列表上使用 mutate 函数。

    我们可以通过首先将值与列名相关联来做到这一点。我们可以在数组中这样做,如下lags &lt;- c(sector = 2, emp = 1, wage = 3, capital = 0)

    然后我们可以构造一个接受列名、值和数据框的函数。这将对数据框进行分组,因为我们要为每个分组变量设置滞后。

    请注意,我们必须在此函数中使用一些元编程工具才能正确使用列名。详情请见https://adv-r.hadley.nz/quasiquotation.html

    在我们的 mutate 函数中,我们使用输入数组使用 !!! 运算符扩展函数列表。在这里,我们通过使用imap 创建我们的函数列表。 imap() 接受一个输入数组、一个函数,我们可以使用 ..x 语法添加额外的输入,其中 x 是一个数字。

    library(tidyverse)
    library(plm)
    data("EmplUK", package = 'plm')
    df <- EmplUK[1:6]
    
    # Add list of colnames and values for functions
    lags <- c(sector = 2, emp = 1, wage = 3, capital = 0)
    
    # Create function to add lags to column
    a <- function(.x, .y, df) {
    # Convert colname to variable
      y <- as.name(.y)
      y <- expr(!!y)
      
    # Return column with lags
      return(
        df %>% 
          group_by_at(1) %>%
          mutate(!!y := dplyr::lag(!!y, .x)) %>%
          `[[`(.y)
      )
    }
    
    # Apply our function to our dataframe using imap
    df %>%
      dplyr::filter(n() > max(lags)) %>%
      dplyr::mutate(!!!imap(lags, ~a(.x, .y, ..3), .))
    #>      firm year sector        emp    wage capital
    #> 1       1 1977     NA         NA      NA  0.5894
    #> 2       1 1978     NA   5.041000      NA  0.6318
    #> 3       1 1979      7   5.600000      NA  0.6771
    #> 4       1 1980      7   5.015000 13.1516  0.6171
    #> 5       1 1981      7   4.715000 12.3018  0.5076
    #> 6       1 1982      7   4.093000 12.8395  0.4229
    #> 7       1 1983      7   3.166000 13.8039  0.3920
    #> 8       2 1977     NA         NA      NA 16.9363
    #> 9       2 1978     NA  71.319000      NA 17.2422
    #> 10      2 1979      7  70.642998      NA 17.5413
    #> 11      2 1980      7  70.917999 14.7909 17.6574
    #> 12      2 1981      7  72.030998 14.1036 16.7133
    #> 13      2 1982      7  73.689003 14.9534 16.2469
    #> 14      2 1983      7  72.418999 15.4910 17.3696
    #> 15      3 1977     NA         NA      NA  7.0975
    #> 16      3 1978     NA  19.156000      NA  6.9469
    #> 17      3 1979      7  19.440001      NA  6.8565
    #> 18      3 1980      7  19.900000 22.6920  6.6547
    #> 19      3 1981      7  20.240000 20.6938  6.2136
    #> 20      3 1982      7  19.570000 21.2048  5.7146
    #> 21      3 1983      7  18.125000 22.1970  7.3431
    #> 22      4 1977     NA         NA      NA  8.4902
    #> 23      4 1978     NA  26.160000      NA  8.7420
    #> 24      4 1979      8  26.740000      NA  9.1869
    #> 25      4 1980      8  27.280001 14.8283  9.4036
    #> 26      4 1981      8  27.830000 14.8379  8.8939
    #> 27      4 1982      8  27.169001 14.8756  8.3905
    #> 28      4 1983      8  24.504000 15.2332  7.4351
    #> 29      5 1976     NA         NA      NA 22.3804
    #> 30      5 1977     NA  86.677002      NA 22.2703
    #> 31      5 1978      7  87.099998      NA 25.1670
    #> 32      5 1979      7  87.000000 20.6323 25.3515
    #> 33      5 1980      7  90.400002 18.2782 28.2394
    #> 34      5 1981      7  89.199997 18.1369 25.7959
    #> 35      5 1982      7  82.699997 18.1896 20.3681
    #> 36      6 1976     NA         NA      NA  0.1694
    #> 37      6 1977     NA   0.748000      NA  0.1618
    #> 38      6 1978      3   0.766000      NA  0.1499
    #> 39      6 1979      3   0.762000 23.1889  0.1458
    #> 40      6 1980      3   0.729000 20.5393  0.1468
    #> 41      6 1981      3   0.731000 20.9387  0.1412
    #> 42      6 1982      3   0.779000 21.7626  0.1261
    #> 43      7 1976     NA         NA      NA  0.9934
    #> 44      7 1977     NA   1.600000      NA  0.9330
    #> 45      7 1978      3   1.650000      NA  0.9650
    #> 46      7 1979      3   1.680000 30.8513  0.9629
    #> 47      7 1980      3   1.680000 28.5550  0.9224
    #> 48      7 1981      3   1.660000 29.8602  0.9992
    #> 49      7 1982      3   1.560000 30.5894  0.8802
    #> 50      8 1976     NA         NA      NA  4.5486
    #> 51      8 1977     NA   9.145001      NA  4.6194
    #> 52      8 1978      3  10.855000      NA  5.0373
    #> 53      8 1979      3  10.749000 30.9089  4.8748
    #> 54      8 1980      3  10.959000 24.4679  3.2221
    #> 55      8 1981      3  10.698000 28.0558  2.8343
    #> 56      8 1982      3   8.174000 28.7445  1.7506
    #> 57      9 1976     NA         NA      NA  0.3824
    #> 58      9 1977     NA   2.006000      NA  0.4551
    #> 59      9 1978      3   2.656000      NA  0.4529
    #> 60      9 1979      3   2.712000 26.0825  0.4524
    #> 61      9 1980      3   2.744000 21.9545  0.4676
    #> 62      9 1981      3   2.757000 22.8100  0.4810
    #> 63      9 1982      3   2.849000 23.3720  0.4753
    #> 64     10 1976     NA         NA      NA  1.1293
    #> 65     10 1977     NA   3.823000      NA  1.0143
    #> 66     10 1978      7   3.935000      NA  1.1169
    #> 67     10 1979      7   3.528000 23.3533  1.1626
    #> 68     10 1980      7   3.520000 21.3251  1.0827
    #> 69     10 1981      7   3.467000 20.9319  1.0636
    #> 70     10 1982      7   3.090000 20.4536  1.0958
    #> 71     11 1976     NA         NA      NA  0.4099
    #> 72     11 1977     NA   1.359000      NA  0.5741
    #> 73     11 1978      3   1.346000      NA  0.5563
    #> 74     11 1979      3   1.338000 23.0614  0.5145
    #> 75     11 1980      3   1.353000 20.2275  0.5895
    #> 76     11 1981      3   1.264000 22.1435  0.4847
    #> 77     11 1982      3   1.158000 22.5496  0.4359
    #> 78     12 1976     NA         NA      NA  0.2569
    #> 79     12 1977     NA   1.780000      NA  0.2072
    #> 80     12 1978      3   1.643000      NA  0.1999
    #> 81     12 1979      3   1.390000 34.2991  0.2007
    #> 82     12 1980      3   1.350000 30.3979  0.1473
    #> 83     12 1981      3   1.082000 31.1431  0.1158
    #> 84     12 1982      3   0.780000 33.3105  0.1036
    #> 85     13 1976     NA         NA      NA  0.5785
    #> 86     13 1977     NA   2.353000      NA  0.5613
    #> 87     13 1978      1   2.386000      NA  0.5273
    #> 88     13 1979      1   2.375000 22.3833  0.5180
    #> 89     13 1980      1   2.415000 23.0607  0.4608
    #> 90     13 1981      1   2.266000 23.4931  0.3750
    #> 91     13 1982      1   1.777000 26.0042  0.3147
    #> 92     14 1978     NA         NA      NA  0.3902
    #> 93     14 1979     NA   3.165000      NA  0.4311
    #> 94     14 1980      1   3.096000      NA  0.4228
    #> 95     14 1981      1   2.991000 20.9113  0.3810
    #> 96     14 1982      1   2.692000 21.8887  0.3051
    #> 97     14 1983      1   2.175000 23.7010  0.2041
    #> 98     14 1984      1   1.801000 21.3925  0.1685
    #> 99     15 1977     NA         NA      NA  1.8498
    #> 100    15 1978     NA   7.220000      NA  1.9215
    #> ...
    

    reprex package (v2.0.0) 于 2021-04-07 创建

    【讨论】:

      【解决方案3】:

      将列名分配给lags,然后将mutate/across 与指定的函数一起使用,该函数在lags 中查找相应的滞后。

      library(dplyr)
      
      lags <- c(2, 1, 3, 0)
      names(lags) <- tail(names(df), length(lags))
      
      df %>%
        group_by(across(1)) %>%
        filter(n() > max(lags)) %>% 
        mutate(across(names(lags), ~ lag(.x, n = lags[[cur_column()]]))) %>%
        ungroup
      

      【讨论】:

        猜你喜欢
        • 2019-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-14
        • 1970-01-01
        • 2019-12-31
        • 1970-01-01
        • 2021-02-28
        相关资源
        最近更新 更多