首页 文章

在R中:如何在两个日期之间按组对变量求和

提问于
浏览
1

我有两个数据帧(DF1和DF2):

(1)DF1包含个人层面的信息,即在11年(2000-2011)内以30个单位嵌套的10,000个人 . 它包含四个变量:

  • "individual"(每个人的数字ID;范围从1-10.000)

  • "unit"(每个单位的数字ID;范围从1-30)

  • "date1"(日期格式的日期,即2000-01-01等;范围从2000-01-01到2010-12-31)

  • "date2"("Date1" 1年)

(2)DF2包含有关单位级别的信息,即在同一时间段(2000-2011)内与DF1相同的30个单位,并且还包含一个数字变量("x"):

  • "unit"(每个单位的数字ID;范围从1-30)

  • "date"(日期格式的日期,即2000-01-01等;范围从2000-01-01至2011-12-31)

  • "x"(一个数字变量,范围从0到200)

我想创建一个新变量(“newvar”),它为每个“单位”给出每个“个体”,“x”(DF2)从“date1”(DF1)到“date2”(DF2)的总和 . 这意味着我想将这个新变量添加到DF1 .

例如,如果“unit”= 1中的“individual”= 1具有“date1”= 2000-01-01且“date2”= 2001-01-01,并且在DF2中“unit”= 1则具有三个时间观察值句点“date1”到“date2”(即2000-01-01到2001-01-01),“x”= 1,“x”= 2,“x”= 3,那么我想添加一个新的变量在“单位”中给出“个人”= 1 = 1“newvar”= 6 .

我假设我需要在R中使用for循环并使用以下代码:

for(i in length(DF1)){

DF1$newvar[i] <-sum(DF2$x[which(DF1$date == DF1$date1[i] &
                     DF1$date == DF1P$date1[i] &
                     DF2$unit == DF1P$unit[i]),])

}

但得到错误信息:

Error in DF2$x[which(DF2$date ==  : incorrect number of dimensions

如何创建这个变量的任何想法将非常感激!

这是一个小例子以及预期输出,为简单起见使用一个单元:

假设DF1如下所示:

individual  unit  date1        date2   
1           1     2000-01-01   2001-01-01
2           1     2000-02-02   2001-02-02
3           1     2000-03-03   2000-03-03
4           1     2000-04-04   2000-04-04
5           1     2000-12-31   2001-12-31 
(...)
996         1     2010-01-01   2011-01-01
997         1     2010-02-15   2011-02-15
998         1     2010-03-05   2011-03-05
999         1     2010-04-10   2011-04-10
1000        1     2010-12-27  2011-12-27
1001        2     2000-01-01   2001-01-01
1002        2     2000-02-02   2001-02-02
1003        2     2000-03-03   2000-03-03
1004        2     2000-04-04   2000-04-04
1005        2     2000-12-31   2001-12-31 
(...)
1996        2     2010-01-01   2011-01-01
1997        2     2010-02-15   2011-02-15
1998        2     2010-03-05   2011-03-05
1999        2     2010-04-10   2011-04-10
2000        2     2010-12-027  2011-12-27
(...)
3000        34    2000-02-02   2002-02-02
3001        34    2000-05-05   2001-05-05
3002        34    2000-06-06   2001-06-06
3003        34    2000-07-07   2001-07-07
3004        34    2000-11-11   2001-11-11
(...)
9996        34    2010-02-06   2011-02-06
9997        34    2010-05-05   2011-05-05
9998        34    2010-09-09   2011-09-09 
9999        34    2010-09-25   2011-09-25
10000       34    2010-10-15   2011-10-15

假设DF2看起来如下:

unit      date         x
1         2000-01-01   1
1         2000-05-01   2
1         2000-12-01   3
1         2001-01-02   10
1         2001-07-05   20
1         2001-12-31   30
(...) 
2         2010-05-05   1 
2         2010-07-01   1
2         2010-08-09   1
3         (...)

这是我希望DF1在运行代码后的样子:

individual  unit      date1        date2        newvar  
    1           1     2000-01-01   2001-01-01   6
    2           1     2000-02-02   2001-02-02   16
    3           1     2000-03-03   2001-03-03   15
    4           1     2000-04-04   2001-04-04   15
    5           1     2000-12-31   2001-12-31   60
    (...)
    996         1     2010-01-01   2011-01-01    3
    997         1     2010-02-15   2011-02-15    2
    998         1     2010-03-05   2011-03-05    2
    999         1     2010-04-10   2011-04-10    2
    1000        1     2010-12-27  2011-12-27     0
    (...)

但是,我不能简单地汇总:想象一下,在DF1中,每个“单位”在2000年到2011年之间每年有数百个人 . 而DF2在2000 - 2011年期间对每个单位都有很多观察 .

2 回答

  • 2

    你几乎就在那里,我只是略微修改你的for循环,并确保日期变量被认为是这样的:

    DF1$date1 = as.Date(DF1$date1,"%Y-%m-%d")
    DF1$date2 = as.Date(DF1$date2,"%Y-%m-%d")
    DF2$date = as.Date(DF2$date,"%Y-%m-%d")
    
    for(i in 1:nrow(DF1)){
      DF1$newvar[i] <-sum(DF2$x[which(DF2$unit == DF1$unit[i] & 
                                      DF2$date>= DF1$date1[i] &
                                      DF2$date<= DF1$date2[i])]) 
    }
    

    问题是,你要求 DF2$date 同时 == DF1$date1DF1$date2 . 而且, length(DF1) 为您提供了列数 . 要获得行数,您可以使用 nrow(DF1)dim(DF1)[1] .

  • 1

    我们可以用 data.table

    library(data.table)
    setDT(DF1)
    setDT(DF2)
    DF1[DF2[, .(newvar = sum(x)), .(unit, individual = cumsum(date %in% DF1$date1))],
                 newvar := newvar, on = .(individual, unit)]
    DF1
    #    individual unit      date1      date2 newvar
    #1:          1    1 2000-01-01 2001-01-01      6
    #2:          2    1 2001-01-02 2002-01-02     60
    

    或者我们可以使用非equi连接

    DF1[DF2[DF1, sum(x), on = .(unit, date >= date1, date <= date2),
            by = .EACHI], newvar := V1, on = .(unit, date1=date)]
    
    DF1
    #   individual unit      date1      date2 newvar
    #1:          1    1 2000-01-01 2001-01-01      6
    #2:          2    1 2001-01-02 2002-01-02     60
    

相关问题