我有一份人员名单,包括他们的出生和死亡日期。
我想创建一个数据集,每个人每年都有一条记录。
我的代码如下:
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年,但这只是为了一个可重复的例子。在我的实际问题中,我正在搞乱从与上述原始数据集类似的数据创建多个时间序列,这就是为什么我想使用秒,分钟等,并保持日期时间格式。
答案 0 :(得分: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
答案 1 :(得分: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))