与组_相比,更快的速度为%>;%在R中展开

与组_相比,更快的速度为%>;%在R中展开,r,performance,dplyr,data.table,data-manipulation,R,Performance,Dplyr,Data.table,Data Manipulation,我试图为R中的多个ID创建一个年序列。我的输入表中每个ID都有一行,并给出一个起始年。看起来是这样的: ID Start_year 01 1999 02 2004 03 2015 04 2007 等等 我需要为每个ID创建一个包含多行的表,显示从起始年到2015年的每一年。然后,我将使用它连接到另一个表。所以在我的例子中,ID1将有17行,年份为1999:2015。ID2将有12行2004:2015,ID3将有1行2

我试图为R中的多个ID创建一个年序列。我的输入表中每个ID都有一行,并给出一个起始年。看起来是这样的:

ID    Start_year
01          1999
02          2004
03          2015
04          2007
等等

我需要为每个ID创建一个包含多行的表,显示从起始年到2015年的每一年。然后,我将使用它连接到另一个表。所以在我的例子中,ID1将有17行,年份为1999:2015。ID2将有12行2004:2015,ID3将有1行2015,ID4将有9行2007:2015

对于我的数据子集,我可以使用以下代码实现这一点:

df %>% group_by(ID) %>% expand(year = Start_year:2015, Start_year) %>% select(-Start_year)
然而,我的完整数据集有大约500万个ID,这个命令似乎非常慢,需要花费很多小时

因此,我希望在R中更快地实现此命令。根据我的经验,data.table命令似乎通常比dplyr/tidyr快-但是,我对data.table语法非常不熟悉。

您可以这样做

out <- DT[, .(col = seq.int(Start_year, 2015L)), by = ID]
out
#    ID  col
# 1:  1 1999
# 2:  1 2000
# 3:  1 2001
# 4:  1 2002
# 5:  1 2003
# 6:  1 2004
# 7:  1 2005
# 8:  1 2006
# 9:  1 2007
# ...

同样想法的一种方式

library(readr); library(dplyr); library(tidyr)
tbl <- read_table(text)

tbl %>% 
  group_by(ID) %>% 
  mutate(Start_year = list(seq.int(Start_year, 2015L))) %>%
  # rename(new_col = Start_year)
  unnest()
库(readr);图书馆(dplyr);图书馆(tidyr)
待定%
分组依据(ID)%>%
突变(起始年=列表(序号int(起始年,2015L))%>%
#重命名(新列=开始年份)
unnest()
数据

text <- "ID    Start_year
01          1999
02          2004
03          2015
04          2007"

library(data.table)
DT <- fread(text)

texttidyverse解决方案可以是:

df <- data.table::fread("
ID    Start_year
01          1999
02          2004
03          2015
04          2007")

library(padr)
library(tidyverse)

df %>% 
  pad_int('Start_year', 
          end_val = 2015, 
          group = "ID")
df%
pad_int(“起始年”,
截至2015年,
group=“ID”)

如果您有足够的内存,您可以使用全套ID x年并使用滚动联接进行筛选:

res <- DT[
  CJ(ID, Start_year = seq.int(min(Start_year), 2015L)), 
  on=.(ID, Start_year), 
  roll=TRUE, 
  nomatch=0
]

setnames(res, "Start_year", "Year")[]

res哇!谢谢你,在几秒钟内就完成了同样的事情!我以前的方法估计需要22小时
res <- DT[
  CJ(ID, Start_year = seq.int(min(Start_year), 2015L)), 
  on=.(ID, Start_year), 
  roll=TRUE, 
  nomatch=0
]

setnames(res, "Start_year", "Year")[]