Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R:按ID和指定数据聚合历史记录_R_Data.table_Dplyr - Fatal编程技术网

R:按ID和指定数据聚合历史记录

R:按ID和指定数据聚合历史记录,r,data.table,dplyr,R,Data.table,Dplyr,我以前也问过类似的问题,得到了很大的帮助: 不同的是,对于前一篇文章,我对汇总所有历史信息感兴趣,但现在我希望只指定90天以前的内容 以下是我的数据的外观示例: strDates <- c("09/09/16", "5/7/16", "5/6/16", "2/13/16", "2/11/16","1/7/16", "11/8/16","6/8/16", "5/8/16","2/13/16","1/3/16", "1/1/16") Date<-as.Date(str

我以前也问过类似的问题,得到了很大的帮助:

不同的是,对于前一篇文章,我对汇总所有历史信息感兴趣,但现在我希望只指定90天以前的内容

以下是我的数据的外观示例:

strDates <- c("09/09/16", "5/7/16", "5/6/16", "2/13/16", "2/11/16","1/7/16",
          "11/8/16","6/8/16", "5/8/16","2/13/16","1/3/16", "1/1/16")
Date<-as.Date(strDates, "%m/%d/%y")
ID <- c("A", "A", "A", "A","A", "A", "B","B","B","B","B", "B")
Event <- c(1,0,1,0,1,1, 0,1,1,1,0, 1)
sample_df <- data.frame(Date,ID,Event)

strDates一个部分矢量化的
dplyr
解决方案,您可以在其中组合
do
(在组中循环)和
行操作(这样您可以将日期引用为每行的日期,
$Date
作为每个组中的整个
Date
列):

sample_df%>%
分组依据(ID)%>%
do(按行(%)%%>%
变异(PrevEnc90D=sum(日期-.$Date<90和日期-.$Date>0),
PrevEvent90D=总和(.$Event[日期-.$Date<90和日期-.$Date>0]))
#来源:本地数据帧[12 x 5]
#组别:ID[2]
#日期ID事件PrevEnc90D Prevent90d
#                       
#1 2016-09-09 A 10 0 0
#2 2016-05-07 A 0 3 2
#3 2016-05-06 A 12 1
#4 2016-02-13 A 0 2 2
#5 2016-02-11a
#6 2016-01-07 A 10 0 0
#7 2016-11-08乙00
#8 2016-06-08 B1
#9 2016-05-08 B1
#10 2016-02-13 B 1 2 1
#11 2016-01-03 B 0 1 1
#12 2016-01-01 B 1 0 0 0

这里有一个替代的
数据表
解决方案,应该非常有效。这利用了v1.10.0中引入的新的非等联接,并结合了
by=.EACHI
,允许您在联接时对每个联接进行计算

library(data.table)#v1.10.0
setDT(sample_df)[,Date2:=Date-90]#设置范围(可能在将来可以避免)
sample_-df[sample_-df,#二进制与自身连接
(Enc90D=0.N,Ev90D=sum(Event,na.rm=TRUE)),进行计算
on=(ID=ID,日期<日期,日期>日期2),#加入
by=.EACHI]#对每一场比赛进行计算
#ID日期Enc90D Ev90D
#1:A 2016-09-09 2016-06-11 0
#2:A 2016-05-07 2016-02-07 3 2
#3:A 2016-05-06 2016-02-06 2 1
#4:A 2016-02-13 2015-11-15 2
#5:A 2016-02-11 2015-11-13 1
#6:A 2016-01-07 2015-10-09
#7:B 2016-11-08 2016-08-10 0
#8:B 2016-06-08 2016-03-10 11
#9:B 2016-05-08 2016-02-08 1
#10:B 2016-02-13 2015-11-15 2 1
#11:B 2016-01-03 2015-10-05 11
#12:B 2016-01-01 2015-10-03 0

一个相当冗长的dplyr解决方案,它使用的行比实际需要的多。其思想是为每个日期创建一个完全联接的表,然后使用窗口函数。如果需要不同的窗口计算,这可能很有用

library(dplyr)

dates <- data.frame(Date = seq(from = -90 + min(sample_df$Date), to = max(sample_df$Date), by=1)) 
extended_df <- data.frame(ID = unique(sample_df$ID)) %>%
  merge(dates) %>% 
  left_join(sample_df, by=(c("ID", "Date"))) %>% 
  arrange(ID, desc(Date)) %>%
  mutate(Encounter = as.integer(!is.na(Event)),
         Event = ifelse(is.na(Event), 0, Event)) %>%
  group_by(ID) %>%
  mutate(PrevEnc90D   = rollsum(lead(Encounter), k=90, fill=0, align="left"),
        PrevEvent90D  = rollsum(lead(Event),     k=90, fill=0, align="left")) %>%
  inner_join(sample_df[,c("ID", "Date")]) %>%
  arrange(ID, desc(Date))

extended_df
库(dplyr)
日期%
左连接(示例df,by=(c(“ID”,“Date”))%>%
安排(ID,描述(日期))%>%
mutate(遭遇=as.integer(!is.na(事件)),
Event=ifelse(is.na(事件),0,事件))%>%
分组依据(ID)%>%
变异(PrevEnc90D=rollsum(引导(遭遇),k=90,fill=0,align=“left”),
PrevEvent90D=rollsum(lead(事件),k=90,fill=0,align=“left”)%%>%
内部联接(样本df[,c(“ID”,“日期”))%>%
安排(ID、描述(日期))
扩展的
来源:本地数据帧[12 x 6] 组别:ID[2]

       ID       Date Event Encounter PrevEnc90D PrevEvent90D
   <fctr>     <date> <dbl>     <int>      <dbl>        <dbl>
1       A 2016-09-09     1         1          0            0
2       A 2016-05-07     0         1          3            2
3       A 2016-05-06     1         1          2            1
4       A 2016-02-13     0         1          2            2
5       A 2016-02-11     1         1          1            1
6       A 2016-01-07     1         1          0            0
7       B 2016-11-08     0         1          0            0
8       B 2016-06-08     1         1          1            1
9       B 2016-05-08     1         1          1            1
10      B 2016-02-13     1         1          2            1
11      B 2016-01-03     0         1          1            1
12      B 2016-01-01     1         1          0            0
ID日期事件遭遇PrevEnc90D prevent90d
1A 2016-09-09 110 0 0
2A 2016-05-07 01 3 2
3A 2016-05-06 11
4a 2016-02-13 01 2
5A 2016-02-11 1
6 A 2016-01-07 11 0 0
7 B 2016-11-08 01 0 0
8 B 2016-06-08 1
9 B 2016-05-08 1
10B 2016-02-13 11
11B 2016-01-03 01
12 B 2016-01-01 11 0 0

以及另一种尽可能避免重复求和和和关系运算的方法:

do.call(rbind, 
        lapply(split(sample_df, sample_df$ID), 
               function(x) {
                   i = nrow(x) - findInterval(x$Date - 90, rev(x$Date))
                   cs = cumsum(x$Event)
                   cbind(x, PrevEnc90D = i - (1:nrow(x)), PrevEvent90D = cs[i] - cs)
               }))
#           Date ID Event PrevEnc90D PrevEvent90D
#A.1  2016-09-09  A     1          0            0
#A.2  2016-05-07  A     0          3            2
#A.3  2016-05-06  A     1          2            1
#A.4  2016-02-13  A     0          2            2
#A.5  2016-02-11  A     1          1            1
#A.6  2016-01-07  A     1          0            0
#B.7  2016-11-08  B     0          0            0
#B.8  2016-06-08  B     1          1            1
#B.9  2016-05-08  B     1          1            1
#B.10 2016-02-13  B     1          2            1
#B.11 2016-01-03  B     0          1            1
#B.12 2016-01-01  B     1          0            0

上面假设“日期”在每个“ID”中按递减顺序排列(如果不是这样的话,这非常简单)。这里的主要思想是:(i)为每个日期确定前90天的位置,(ii)计算一次预先累积的总和,(iii)减去相应的指数/
cumsum
s以获得输出。我在这里使用了
split
/
lappy
路线,以“ID”进行分组,但我想,它很容易转移到任何更好的工具上。

我很欣赏这个解决方案,并将很快试用它!我应该补充一点,我有一个非常小的数据集(
       ID       Date Event Encounter PrevEnc90D PrevEvent90D
   <fctr>     <date> <dbl>     <int>      <dbl>        <dbl>
1       A 2016-09-09     1         1          0            0
2       A 2016-05-07     0         1          3            2
3       A 2016-05-06     1         1          2            1
4       A 2016-02-13     0         1          2            2
5       A 2016-02-11     1         1          1            1
6       A 2016-01-07     1         1          0            0
7       B 2016-11-08     0         1          0            0
8       B 2016-06-08     1         1          1            1
9       B 2016-05-08     1         1          1            1
10      B 2016-02-13     1         1          2            1
11      B 2016-01-03     0         1          1            1
12      B 2016-01-01     1         1          0            0
do.call(rbind, 
        lapply(split(sample_df, sample_df$ID), 
               function(x) {
                   i = nrow(x) - findInterval(x$Date - 90, rev(x$Date))
                   cs = cumsum(x$Event)
                   cbind(x, PrevEnc90D = i - (1:nrow(x)), PrevEvent90D = cs[i] - cs)
               }))
#           Date ID Event PrevEnc90D PrevEvent90D
#A.1  2016-09-09  A     1          0            0
#A.2  2016-05-07  A     0          3            2
#A.3  2016-05-06  A     1          2            1
#A.4  2016-02-13  A     0          2            2
#A.5  2016-02-11  A     1          1            1
#A.6  2016-01-07  A     1          0            0
#B.7  2016-11-08  B     0          0            0
#B.8  2016-06-08  B     1          1            1
#B.9  2016-05-08  B     1          1            1
#B.10 2016-02-13  B     1          2            1
#B.11 2016-01-03  B     0          1            1
#B.12 2016-01-01  B     1          0            0