在R中作为数据帧元素的列表上的操作
我有一个ID的时间序列,以及事件发生的日期列表。我想知道在我的时间序列中,在给定的日期之前,事件发生了多少次 以下是一个示例数据帧:在R中作为数据帧元素的列表上的操作,r,list,dataframe,R,List,Dataframe,我有一个ID的时间序列,以及事件发生的日期列表。我想知道在我的时间序列中,在给定的日期之前,事件发生了多少次 以下是一个示例数据帧: ID <- c(1,1,1,2,2,2,3,3,3) date <- c(2000,2001,2002) df <- data.frame(ID,date) rand1 <- c(runif(5)*4+1999) rand2 <- c(runif(6)*4+1999) rand3 <- c(runif(100)*4+1999)
ID <- c(1,1,1,2,2,2,3,3,3)
date <- c(2000,2001,2002)
df <- data.frame(ID,date)
rand1 <- c(runif(5)*4+1999)
rand2 <- c(runif(6)*4+1999)
rand3 <- c(runif(100)*4+1999)
df$events <- list(rand1, rand1, rand1, rand2, rand2, rand2,rand3, rand3, rand3 )
IDdf$past2的问题是df$events[[1]]
始终返回df[1,]$df$events[[1]]
解决此问题的一个方法是将数据帧的每一行拆分为一个列表,并使用Lappy:
df$past2 = unlist(lapply(split(df,seq(nrow(df))),function(x) sum(x$events[[1]]< x$date)))
df$pass2=unlist(lapply(拆分(df,seq(nrow(df))),函数(x)和(x$events[[1]]
然而,由于存在一些数据操作,我不确定这对于400万行数据帧是否非常有效。您可能需要查看data.table
或dplyr
以找到更有效的解决方案 您可以使用tidyr::unnest()
为每个事件创建一行,然后dplyr::filter()
为感兴趣日期之后发生的事件创建一行 1)您的df$past2
计算返回事件列表的第一个值小于日期列中的值的行数,然后将整个列设置为该值。括号中的表达式返回TRUE
或FALSE
,并解释为
调用sum()时1
或0
。例如sum(真、真、假)
返回2
2) 使用tidyr::unest()
函数以及dplyr
包中的函数,可以执行以下操作:
df2 <- df %>%
unnest(events) %>%
group_by(ID, date) %>%
mutate(past = if_else(events < date, 1, 0)) %>%
summarize(past2 = sum(past))
df2%
unnest(事件)%%>%
分组人(ID,日期)%>%
突变(过去=if_else(事件<日期,1,0))%>%
汇总(过去2=总和(过去))
这个答案和@xraynaud的答案都适用于我的示例问题,但根据这两种方法的microbenchmark结果,这个方法的速度快了100倍。编辑以添加相同代码的单位不相同。。。重新检查并在单位正确后更新。好的,在单位正确后:unlist的平均时间为732微秒,Unest的平均时间为4060微秒。这种方法的代码更容易阅读和理解,因此我认为在很多情况下,它可能是正确的选择。
ID date events past past2
<dbl> <dbl> <list> <dbl> <int>
1 2000 <dbl [5]> 3 6
1 2001 <dbl [5]> 3 6
1 2002 <dbl [5]> 4 6
2 2000 <dbl [6]> 0 6
2 2001 <dbl [6]> 3 6
2 2002 <dbl [6]> 5 6
3 2000 <dbl [100]> 26 6
3 2001 <dbl [100]> 55 6
3 2002 <dbl [100]> 74 6
df$past2 = unlist(lapply(split(df,seq(nrow(df))),function(x) sum(x$events[[1]]< x$date)))
df2 <- df %>%
unnest(events) %>%
group_by(ID, date) %>%
mutate(past = if_else(events < date, 1, 0)) %>%
summarize(past2 = sum(past))