2016-08-24 94 views
1

我有一个人员列表,他们的出生和死亡日期。data.table中的有效日期差异

我想创建一个数据集,每个人每年都有一个记录。

我的代码如下:

library(lubridate) 
library(data.table) 
deadPerson<-c("Albert Einstein","Erwin Schrodinger","Paul Dirac") 
dateOfBirth<-c("1879-03-14","1887-08-12","1902-08-08") 
dateOfDeath<-c("1955-04-18","1961-01-04","1984-10-20") 

df<-data.frame(cbind(deadPerson,dateOfBirth,dateOfDeath)) 

df$dateOfBirth<-as.POSIXct(df$dateOfBirth) 
df$dateOfDeath<-as.POSIXct(df$dateOfDeath) 

for(i in 1:dim(df)[1]) 
{ 
    birth_day<-df$dateOfBirth[i] 
    death_day<-df$dateOfDeath[i] 
    numDays<-as.numeric(death_day-birth_day) 
    numYears<-floor(numDays/365) # ignore leap years! 
    dates <- data.table(index=as.POSIXct(birth_day) + (0:numYears)*years(1)) 
    dates$Person<-df$deadPerson[i] 
    if(i==1){output<-dates} 
    else{output<-rbind(output,dates)} 
} 
output$index<-year(output$index) 
colnames(output)<-c("Year.Alive","Person") 

我做的逻辑是遍历每个人,并创造每年他们还活着的记录。当然这是低效的,但是我无法找到一种有效的方法(例如使用apply())。

有没有更好的方法在数据表中做到这一点?

PS - 我知道我应该在最初的数据集中使用多年,只需添加1年,但这仅仅是为了一个可重复的例子。在我的实际问题中,我正在搞乱从数据创建多个时间序列的格式与上面的原始数据集,这就是为什么我想使用秒,分钟等,并保持日期时间格式。

回答

4

您可以使用组总结语法data.table,并计算在j位置多年载体,沿着该组变量会自动播放:

library(data.table) 
df[, .(Year.Alive = seq(year(dateOfBirth), year(dateOfDeath))), by = (Person = deadPerson)] 

#    Person Year.Alive 
# 1: Albert Einstein  1879 
# 2: Albert Einstein  1880 
# 3: Albert Einstein  1881 
# 4: Albert Einstein  1882 
# 5: Albert Einstein  1883 
# ---       
# 231:  Paul Dirac  1980 
# 232:  Paul Dirac  1981 
# 233:  Paul Dirac  1982 
# 234:  Paul Dirac  1983 
# 235:  Paul Dirac  1984 
+0

@DavidArenburg想要导入'year'函数。但我想你是对的,它也带有'data.table'。 – Psidom

0

这里是一个tidyr/dplyr版本:

library(dplyr) 
library(tidyr) 

df %>% 
    gather(date, event, dateOfBirth, dateOfDeath) %>% 
    mutate(year_event = year(event)) %>% 
    select(deadPerson, year_event) %>% 
    group_by(deadPerson) %>% 
    complete(year_event = full_seq(year_event, period = 1L))