带条件的前向填充数据

问题描述

我有一个数据框 DF,看起来像这样:

    date permno   ret sue  bm gpa
1  202001  10000  0.01 0.4 0.4  NA
2  202002  10000  0.04  NA  NA 0.5
3  202003  10000 -0.01  NA  NA  NA
4  202004  10000  0.00 1.3 0.5  NA
5  202005  10000  0.02  NA  NA 0.3
6  202006  10000  0.01  NA  NA  NA
7  202007  10000  0.03  NA  NA  NA
8  202008  10000 -0.02  NA  NA 0.4
9  202001  11000  0.05 0.1 0.3  NA
10 202002  11000  0.02  NA  NA  NA
11 202003  11000  0.01  NA  NA  NA
12 202004  11000  0.00  NA  NA 0.3
13 202005  11000  0.01  NA  NA  NA
14 202006  11000 -0.01  NA  NA  NA
15 202007  11000  0.04 0.5 0.4  NA
16 202008  11000  0.30  NA  NA  NA

我正在使用此代码向前填充变量 sue、bm 和 gpa:

DF1 <- 
  DF %>%
  arrange(permno,date) %>%
  group_by(permno) %>%
  mutate_at(vars(c(sue,bm,gpa)),funs(na.locf(.,na.rm=FALSE)))

结果如下

  date permno   ret   sue    bm   gpa

 1 202001  10000  0.01   0.4   0.4  NA  
 2 202002  10000  0.04   0.4   0.4   0.5
 3 202003  10000 -0.01   0.4   0.4   0.5
 4 202004  10000  0      1.3   0.5   0.5
 5 202005  10000  0.02   1.3   0.5   0.3
 6 202006  10000  0.01   1.3   0.5   0.3
 7 202007  10000  0.03   1.3   0.5   0.3
 8 202008  10000 -0.02   1.3   0.5   0.4
 9 202001  11000  0.05   0.1   0.3  NA  
10 202002  11000  0.02   0.1   0.3  NA  
11 202003  11000  0.01   0.1   0.3  NA  
12 202004  11000  0      0.1   0.3   0.3
13 202005  11000  0.01   0.1   0.3   0.3
14 202006  11000 -0.01   0.1   0.3   0.3
15 202007  11000  0.04   0.5   0.4   0.3
16 202008  11000  0.3    0.5   0.4   0.3

我想限制数据向前填充的月份数。我想向前填充三个变量,直到下一个可用值,但最多 3 个月。因此,结果应如下所示:

    date permno   ret sue  bm gpa
1  202001  10000  0.01 0.4 0.4  NA
2  202002  10000  0.04 0.4 0.4 0.5
3  202003  10000 -0.01 0.4 0.4 0.5
4  202004  10000  0.00 1.3 0.5 0.5
5  202005  10000  0.02 1.3 0.5 0.3
6  202006  10000  0.01 1.3 0.5 0.3
7  202007  10000  0.03 1.3 0.5 0.3
8  202008  10000 -0.02  NA  NA 0.4
9  202001  11000  0.05 0.1 0.3  NA
10 202002  11000  0.02 0.1 0.3  NA
11 202003  11000  0.01 0.1 0.3  NA
12 202004  11000  0.00 0.1 0.3 0.3
13 202005  11000  0.01  NA  NA 0.3
14 202006  11000 -0.01  NA  NA 0.3
15 202007  11000  0.04 0.5 0.4 0.3
16 202008  11000  0.30 0.5 0.4  NA

有谁知道我如何在 R 中做到这一点?

解决方法

我们可以编写自己的 na.locf() 来进行您想要的调整:

代码

library(zoo)
library(dplyr)

na.locf2 <- function(object,period = 3,...){
  # consecutive NAs
  tmp1 <- rle(is.na(object))
  
  # NA count in the length of the vector 
  tmp2 <- unlist(sapply(tmp1[[1]],function(x){
          1:x
          }))
  
  # remove all NAs
  tmp3 <- na.locf(object,...)
  
  # reassign those that are greater than the desired period
  tmp3[tmp2 > period] <- NA
  
  # return 
  tmp3
}

# Then 

DF %>%
  arrange(permno,date) %>%
  group_by(permno) %>%
  mutate_at(vars(c(sue,bm,gpa)),funs(na.locf2(.,na.rm=FALSE)))

# Yields

# A tibble: 16 x 6
# Groups:   permno [2]
#     date permno   ret   sue    bm   gpa
#    <int>  <int> <dbl> <dbl> <dbl> <dbl>
#  1 202001  10000  0.01   0.4   0.4  NA  
#  2 202002  10000  0.04   0.4   0.4   0.5
#  3 202003  10000 -0.01   0.4   0.4   0.5
#  4 202004  10000  0      1.3   0.5   0.5
#  5 202005  10000  0.02   1.3   0.5   0.3
#  6 202006  10000  0.01   1.3   0.5   0.3
#  7 202007  10000  0.03   1.3   0.5   0.3
#  8 202008  10000 -0.02  NA    NA     0.4
#  9 202001  11000  0.05   0.1   0.3  NA  
# 10 202002  11000  0.02   0.1   0.3  NA  
# 11 202003  11000  0.01   0.1   0.3  NA  
# 12 202004  11000  0      0.1   0.3   0.3
# 13 202005  11000  0.01  NA    NA     0.3
# 14 202006  11000 -0.01  NA    NA     0.3
# 15 202007  11000  0.04   0.5   0.4   0.3
# 16 202008  11000  0.3    0.5   0.4  NA  

,

这听起来像是滚动窗口的事情。但是,由于您需要限制结转,一个问题是当您查看特定单元格时,它的前任已经修复(未-_conditions.mat'd),因此我们需要查看NAerse 中的向量。

一个辅助函数,其中 rev 取决于您的偏好,不超过三个月。在反转 2:4 的上下文中,本例中的 rollapply 可能是 z[1],其中 NA 是三个个月。

z[2:4]

由于我们在滚动中使用了 func <- function(z) if (is.na(z[1])) na.omit(z[2:4])[1] else z[1] ,因此 partial=TRUE 不会是长度 4 是可行的;不过,这很好,因为即使是 z 也会返回 z[100000],它由 NA 明确处理。 (这种情况也可以通过对 na.omit 的测试来解决。)

另一个注意事项:length(z) 可以返回一个长度为 0 的向量,这在这种情况下显然是不好的。但是,在它之后添加 na.omit(.) 会强制它返回一个 [1],如果 NA 中不存在非NA 元素,我们需要它。

从这里开始,大部分工作由z[2:4]完成:

zoo::rollapply