如何在R中进行面板数据的差分

6
我想知道是否有简单的R命令或软件包,可以让我轻松地将变量添加到数据框中,这些变量是随时间“差异”或变化的结果。
如果我的数据看起来像这样:
set.seed(1)
MyData <- data.frame(Day=0:9 %% 5+1, 
                 Price=rpois(10,10),
                 Good=rep(c("apples","oranges"), each=5))
MyData

   Day Price    Good
1    1     8  apples
2    2    10  apples
3    3     7  apples
4    4    11  apples
5    5    14  apples
6    1    12 oranges
7    2    11 oranges
8    3     9 oranges
9    4    14 oranges
10   5    11 oranges

然后,对价格变量进行“首次差分”处理之后,我的数据如下所示。
   Day Price    Good P1d
1    1     8  apples  NA
2    2    10  apples   2
3    3     7  apples  -3
4    4    11  apples   4
5    5    14  apples   3
6    1    12 oranges  NA
7    2    11 oranges  -1
8    3     9 oranges  -2
9    4    14 oranges   5
10   5    11 oranges  -3
7个回答

11

ave

transform(MyData, P1d = ave(Price, Good, FUN = function(x) c(NA, diff(x))))

ave/gsubfn

可以使用 gsubfn 包中的 fn$ 稍微缩短最后的解决方案:

library(gsubfn)
transform(MyData, P1d = fn$ave(Price, Good, FUN = ~ c(NA, diff(x))))

dplyr

library(dplyr)

MyData %>% 
  group_by(Good) %>% 
  mutate(P1d = Price - lag(Price)) %>% 
  ungroup

data.table

library(data.table)

dt <- data.table(MyData)
dt[, P1d := c(NA, diff(Price)), by = Good]

更新

dplyr现在使用%>% 而不是%.%


2
可以这样轻松地完成:

library(reshape2)
library(dplyr)

MyNewData <- 
 MyData %.%
 melt(id = c("Good", "Day")) %.%
 dcast(Day ~ Good) %.%
 mutate(apples  = apples - lag(apples),
     oranges = oranges - lag(oranges)) %.%
 melt(id = "Day", variable.name = "Good", value.name = "P1d") %.%
 merge(MyData) %.%
 arrange(Good, Day)

敬礼


谢谢您提供的解决方案,虽然我不确定是否会说“容易”。对我来说,这似乎相当复杂。特别是考虑到一旦设置了面板和时间序列标识符,Stata将执行相同的命令(gen P1d = Price-L1.Price)。 - Francis Smart

1
在我的情况下,我需要为一个面板生成一阶差分。为了使差分向量具有相同的长度,我使用带有NA的diff函数。
library(dplyr)
mydata %>%
group_by(id) %>%
mutate(price_diff = c(NA, diff(price)))%>%
ungroup()

0
我是根据一些在线dpylr教程编写了这段代码: 我的目标是添加一个新列,该列是公司(identifer GVKEY)的研发(变量xrd)的5年增长率。RandD2015是原始数据文件。
通过使用管道函数(%>%),您可以在dplyr中组合多个调用。希望这对您有用(这是我在Stack Overflow上的第一个代码贡献)。
library(dplyr)

RandDtest<- RandDec2015 %>% 
    group_by(GVKEY) %>%
    mutate(xrd5yr=xrd/lag(xrd,4)-1)

0

如果数据是不平衡的,例如askesis_rea的答案G. Grothendieck的答案不能直接应用(注意:我没有测试其他答案)。但是,在将数据框扩展为带有NA值的平衡面板后,它们适用。

示例

在此示例中,个体未在所有时间段内被观察到。

让我们将示例扩展到不平衡的情况:(我删除了苹果的第二天)

set.seed(1)
mydata <- data.frame(Day=0:9 %% 5+1, 
                 Price=rpois(10,10),
                 Good=rep(c("apples","oranges"), each=5))
mydata <- mydata[!(mydata$Good=="apples" & mydata$Day==2), ]# removing apples in day 2
mydata

   Day Price    Good
1    1     8  apples
3    3     7  apples
4    4    11  apples
5    5    14  apples
6    1    12 oranges
7    2    11 oranges
8    3     9 oranges
9    4    14 oranges
10   5    11 oranges

运行G. Grothendieck的dplyr答案会产生错误的值:

mydata %>% 
  group_by(Good) %>% 
  mutate(P1d = Price - lag(Price)) %>% 
  ungroup

实际上,对于第三天和苹果来说,价值应该是2,但实际上它是-1。这是因为计算的是第三天和第一天价格之间的差异,而不是第三天和第二天之间的差异。

# A tibble: 9 × 4
    Day Price Good      P1d
  <dbl> <int> <chr>   <int>
1     1     8 apples     NA
2     3     7 apples     -1
3     4    11 apples      4
4     5    14 apples      3
5     1    12 oranges    NA
6     2    11 oranges    -1
7     3     9 oranges    -2
8     4    14 oranges     5
9     5    11 oranges    -3

但是如果我们先进行扩展,然后再应用第一阶差分,就可以得到正确的结果:

library(tidyr)
expanded <- mydata %>%  complete(nesting(Good), Day=full_seq(Day, 1))

expanded %>% 
  group_by(Good) %>% 
  mutate(P1d = Price - lag(Price)) %>% 
  ungroup

# A tibble: 10 × 4
   Good      Day Price   P1d
   <chr>   <dbl> <int> <int>
 1 apples      1     8    NA
 2 apples      2    NA    NA
 3 apples      3     7    NA
 4 apples      4    11     4
 5 apples      5    14     3
 6 oranges     1    12    NA
 7 oranges     2    11    -1
 8 oranges     3     9    -2
 9 oranges     4    14     5
10 oranges     5    11    -3

编辑

在个体组成随时间变化的其他某些情况下,这种方法可能不适用。 一个好的工具是fixest::d运算符。 它可以在fixest模型公式或data.table中使用。

使用data.table的示例

  1. 不平衡
library(data.table)
# creating the data
set.seed(1)
mydata <- data.frame(Day=0:9 %% 5+1, 
                 Price=rpois(10,10),
                 Good=rep(c("apples","oranges"), each=5))
mydata <- mydata[!(mydata$Good=="apples" & mydata$Day==2), ]# removing apples in day 2

mydata <- fixest::panel(as.data.table(mydata), panel.id=~Good + Day)
mydata[, P1D:=fixest::d(Price)] # Adding inplace first difference 

as.data.frame(fixest::unpanel(mydata)) # viewing

  Day Price    Good P1D
1   1     8  apples  NA
2   3     7  apples  NA
3   4    11  apples   4
4   5    14  apples   3
5   1    12 oranges  NA
6   2    11 oranges  -1
7   3     9 oranges  -2
8   4    14 oranges   5
9   5    11 oranges  -3
  • 平衡的
  • set.seed(1)
    MyData <- data.frame(Day=0:9 %% 5+1, 
                     Price=rpois(10,10),
                     Good=rep(c("apples","oranges"), each=5))
    
    MyData <- fixest::panel(as.data.table(MyData), panel.id=~Good + Day)
    MyData[, P1D:=fixest::d(Price)]
    as.data.frame(fixest::unpanel(MyData))
    

    [1] TRUE
       Day Price    Good P1D
    1    1     8  apples  NA
    2    2    10  apples   2
    3    3     7  apples  -3
    4    4    11  apples   4
    5    5    14  apples   3
    6    1    12 oranges  NA
    7    2    11 oranges  -1
    8    3     9 oranges  -2
    9    4    14 oranges   5
    10   5    11 oranges  -3
    

    0

    这是我想出来的。但它似乎一点也不高效:

    MyData$P1d <- c(NA, MyData$Price[-1]-MyData$Price[-nrow(MyData)])
    MyData$P1d[c(F,MyData$Good[-1]!=MyData$Good[-nrow(MyData)])] <- NA
    
    MyData
    
       Day Price    Good P1d
    1    1     8  apples  NA
    2    2    10  apples   2
    3    3     7  apples  -3
    4    4    11  apples   4
    5    5    14  apples   3
    6    1    12 oranges  NA
    7    2    11 oranges  -1
    8    3     9 oranges  -2
    9    4    14 oranges   5
    10   5    11 oranges  -3
    

    0

    collapse::fdiff 是你要找的函数:

    library(collapse)
    # This means compute difference of Price lagged once, iterated once, by Good, ordered by Day
    settransform(MyData, P1d = fdiff(Price, 1, 1, Good, Day))
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接