我有一个如下所示的数据框:
id date
1001 2012-10-11
1005 2013-02-20
1005 2012-11-21
1005 2014-03-14
1003 2013-10-25
1003 2013-11-30
我需要为每一行找到自该ID最后一次出现以来经过的天数。对于上面的例子,答案如下:
id date no_of_days
1001 2012-10-11 NA
1005 2013-02-20 91
1005 2012-11-21 NA
1005 2014-03-14 387
1003 2013-10-25 NA
1003 2013-11-30 36
通过一些搜索,我可以添加一个新列,其中包含通过在子组上应用函数生成的值(R等效于STATA' s" bysort"):
df$no_of_days<-with(df,ave(id,id,FUN=days_passed,na.rm=TRUE))
然而,定义新函数days_passed证明是棘手的,因为我必须找到该uniqid的最后一次出现,然后相应地制定该函数。
我是R的新手,所以对此有任何帮助将不胜感激。谢谢!
答案 0 :(得分:4)
使用data.table
包可以尝试以下方法(尽管它不保留顺序)。假设df
是您的数据集
library(data.table)
setkey(setDT(df)[, date := as.Date(date)], id, date) # If `date` is already of `Date` class you can skip the `as.Date` part
df[, no_of_days := c(NA, diff(date)) , by = id][]
# id date no_of_days
# 1: 1001 2012-10-11 NA
# 2: 1003 2013-10-25 NA
# 3: 1003 2013-11-30 36
# 4: 1005 2012-11-21 NA
# 5: 1005 2013-02-20 91
# 6: 1005 2014-03-14 387
或者(如@Arun建议的那样)您可以使用order
代替setkey
来保留订单
setDT(df)[, date := as.Date(date)][order(id, date),
no := c(NA, diff(date)), by = id][]
还可以尝试dplyr
library(dplyr)
df %>%
mutate(date = as.Date(date)) %>%
arrange(id, date) %>%
group_by(id) %>%
mutate(no_of_days = c(NA, diff(date)))
答案 1 :(得分:2)
或使用ave
(类似于@David Arenburg的方法)
indx <- with(df, order(id, date))
df1 <- transform(df[indx,], no_of_days=ave(as.numeric(date), id,
FUN= function(x) c(NA, diff(x))))[order(indx),]
df1
# id date no_of_days
#1 1001 2012-10-11 NA
#2 1005 2013-02-20 91
#3 1005 2012-11-21 NA
#4 1005 2014-03-14 387
#5 1003 2013-10-25 NA
#6 1003 2013-11-30 36
df <- structure(list(id = c(1001L, 1005L, 1005L, 1005L, 1003L, 1003L
), date = structure(c(15624, 15756, 15665, 16143, 16003, 16039
), class = "Date")), .Names = c("id", "date"), row.names = c(NA,
-6L), class = "data.frame")