我正在尝试为R中的多个ID创建一个多年的序列。我的输入表为每个ID都有一行,并给出一个Start_year。它看起来像这样:
ID Start_year1999年1月02 …
一个整合的解决方案可能是:
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")
你可以做到
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 # ...
在你的情况下,你可能需要这样做
setDT(df)[, .(col = seq.int(Start_year, 2015L)), by = ID]
一个 tidyverse 同样想法的方式
tidyverse
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()
的 数据 强>
text <- "ID Start_year 01 1999 02 2004 03 2015 04 2007" library(data.table) DT <- fread(text)
如果你有足够的内存,你可以使用x年的全套ID并使用滚动连接进行过滤:
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")[]
CJ 采用ID和年的向量的“交叉连接”。如果您没有使用最新版本的data.table,则可能需要为两个参数命名(即, CJ(ID = ID, Start_year = seq.int(min(Start_year), 2015L)) )。
CJ
CJ(ID = ID, Start_year = seq.int(min(Start_year), 2015L))
评论 。 OP表示@markus的方法已经将操作降低到几秒钟,因此可能不需要进一步改进......而且,我不确定在任何情况下我的方法会更快。