使用 zoo 或更好的包从 R 中的数据框中减去两个因素的行

subtract rows from data frame in R with two factors using zoo or better package

我有一个 data.frame 按公司 ("gvkey") 和日历季度 ("datafqtr") 和附加变量(例如,"day")

gvkey datafqtr  dvy
1  1001   1983Q1 0.50
2  1001   1983Q2 1.50
3  1001   1983Q3 2.00
4  1001   1983Q4 4.50
5  1002   1984Q1 0.00
6  1002   1984Q2 0.00
7  1002   1984Q3 0.10
8  1002   1984Q4 0.45

在 R 中执行以下操作的最佳方法是什么? (不一定使用动物园?)

为此 data.frame,对于每家公司和每一年,从第四季度减去第三季度,然后从第一季度减去第二季度,最后从第二季度减去第一季度。

输出应如下所示:

gvkey datafqtr  dvy
1  1001   1983Q1 0.50
2  1001   1983Q2 1.00
3  1001   1983Q3 0.50
4  1001   1983Q4 2.50
5  1002   1984Q1 0.00
6  1002   1984Q2 0.00
7  1002   1984Q3 0.10
8  1002   1984Q4 0.35

我想通过以下方式进行:

使用 zoo 包并滞后每个变量一次,同时将公司代码 ("gvkey") 和日历季度 (datafqtr) 作为因子,然后减去观察值。

data<-zoo(data)

data<-data[order(data[,'gvkey'],data[,'datafqtr']),]

data$lagfqtr<-lag(data$datafqtr,-1,na.pad=TRUE)
data$laggvkey<-lag(data$gvkey,-1,na.pad=TRUE)

data$lagdvy<-lag(data$dvy,-1,na.pad=TRUE)

然后我将动物园转换为常规 data.frame 并从非滞后变量中减去滞后变量:

data<-as.data.frame(data)

data[,] <- lapply(data[,], function(x) as.numeric(as.character(x)))

indice <- indice*1

data$divq <- data$dvy - (data$lagdvy * indice)

我不确定这是否符合我的要求,

感谢您的帮助,

同样,您可以按照以下方式在data.table中完成您想做的事情。顺便说一下,我认为您不需要移动前两列。

library(data.table)
setDT(data)[order(gvkey, datafqtr)][,dvy1 := Reduce("-", shift(dvy, n = 0:1, type = "lag", fill = 0)), .(gvkey)]
data
   gvkey datafqtr  dvy dvy1
1:  1001   1983Q1 0.50 0.50
2:  1001   1983Q2 1.50 1.00
3:  1001   1983Q3 2.00 0.50
4:  1001   1983Q4 4.50 2.50
5:  1002   1984Q1 0.00 0.00
6:  1002   1984Q2 0.00 0.00
7:  1002   1984Q3 0.10 0.10
8:  1002   1984Q4 0.45 0.35

使用库 dplyr,您可以这样做(从当前值中减去滞后值):

library(dplyr)
df %>%
  group_by(gvkey) %>%
  mutate(dvy = dvy - lag(dvy, default = 0))

输出如下和期望的:

Source: local data frame [8 x 3]
Groups: gvkey [2]

  gvkey datafqtr   dvy
  <int>    <chr> <dbl>
1  1001   1983Q1  0.50
2  1001   1983Q2  1.00
3  1001   1983Q3  0.50
4  1001   1983Q4  2.50
5  1002   1984Q1  0.00
6  1002   1984Q2  0.00
7  1002   1984Q3  0.10
8  1002   1984Q4  0.35

注意:如果数据已经订购,这将起作用。否则,你只需要在上面的管道中引入 arrange 函数,一切都应该就位。

假设data是最后注释中的数据框试试这个:

transform(data, dvy = ave(dvy, gvkey, floor(datafqtr), FUN = function(x) c(x[1], diff(x))))

给予:

  gvkey datafqtr  dvy
1  1001  1983 Q1 0.50
2  1001  1983 Q2 1.00
3  1001  1983 Q3 0.50
4  1001  1983 Q4 2.50
5  1002  1984 Q1 0.00
6  1002  1984 Q2 0.00
7  1002  1984 Q3 0.10
8  1002  1984 Q4 0.35

注意:为了可重复性,使用的输入数据框是这个(其中 datafqtr 列是动物园包 class "yearqtr" ):

data <- structure(list(gvkey = c(1001, 1001, 1001, 1001, 1002, 1002, 
  1002, 1002), datafqtr = structure(c(1983, 1983.25, 1983.5, 1983.75, 
  1984, 1984.25, 1984.5, 1984.75), class = "yearqtr"), dvy = c(0.5, 
  1.5, 2, 4.5, 0, 0, 0.1, 0.45)), .Names = c("gvkey", "datafqtr", 
  "dvy"), row.names = c(NA, -8L), class = "data.frame")