Вычесть строки из фрейма данных в 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")