Вычесть строки из фрейма данных в R с двумя факторами, используя zoo или лучший пакет

У меня есть 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 для каждой компании и для каждого года вычтите 3-й квартал из четвертого квартала, затем второй квартал из первого квартала и, наконец, первый квартал из второго квартала.

Вывод должен выглядеть так:

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)

Я не уверен, что это делает то, что я хочу,

спасибо и ценю всю вашу помощь,

3 ответа

Решение

Использование библиотеки 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.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

Если предположить, что 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 столбец из класса пакета зоопарка "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")
Другие вопросы по тегам