在列表上操作作为R中的数据帧的元素

时间:2017-07-25 20:33:33

标签: 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)

df$events <- list(rand1, rand1, rand1, rand2, rand2, rand2,rand3, rand3, rand3 )

此代码确实正确解决了我的问题:

for (i in c(1:9)){
  print(i)
  df[i,]$past <- sum( df[i,]$events[[1]] < df[i,]$date)
}

但是,逐行浏览数据框似乎非常低效。我的真实数据集有400万行,所以我需要一些更明智的东西。

以下是我首先尝试的内容:我不确定它到底做了什么,但它最终会将df $ past2的所有元素创建为某个整数。

df$past2 <- sum(df$events[[1]] < df$date)

结果df:

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

所以,

1)我的df$past2计算到底在做什么?

2)有没有办法在不是一行一行的数据帧元素的列表上进行这种操作?

感谢。

3 个答案:

答案 0 :(得分:2)

1)您的df$past2计算返回事件列表的FIRST值小于日期列中的值的行数,然后将整个列设置为此值。括号中的表达式返回TRUEFALSE,并被解释为 致电1时,0sum()。例如,sum(TRUE, TRUE, FALSE)会返回2

2)使用tidyr::unnest()函数以及dplyr包中的函数,您可以执行以下操作:

df2 <- df %>%
  unnest(events) %>%
  group_by(ID, date) %>%
  mutate(past = if_else(events < date, 1, 0)) %>%
  summarize(past2 = sum(past))

答案 1 :(得分:1)

你的df $ past2的问题是df$events[[1]]总是返回df[1,]$df$events[[1]]

您的问题的一个解决方案是将数据框的每一行拆分为一个列表并使用lapply:

df$past2 = unlist(lapply(split(df,seq(nrow(df))),function(x) sum(x$events[[1]]< x$date)))

但是,由于存在一些数据操作,我不确定这对于400万行数据帧来说是非常有效的。您可能需要查看data.tabledplyr以找到更有效的解决方案。

答案 2 :(得分:0)

您可以使用tidyr::unnest()为每个事件创建一行,然后dplyr::filter()用于在感兴趣的日期之后发生的事件。