我有以下数据。
df <- data.frame(CustID = c(1,2,3,4,5,1,5),
CustName = c("Fred","Maria","John","Mark", "Julia","Fred","Julia"),
ServiceDate = c('2010-11-1','2008-3-25','2007-3-14','2010-11-1','2008-3-25','2010-12-14','2008-3-14'), stringsAsFactors = F)
df$ServiceDate <- as.Date(df$ServiceDate, "%Y-%m-%d")
df
CustID CustName ServiceDate
1 1 Fred 2010-11-01
2 2 Maria 2008-03-25
3 3 John 2007-03-14
4 4 Mark 2010-11-01
5 5 Julia 2008-03-25
6 1 Fred 2010-12-14
7 5 Julia 2008-03-14
我需要找出一种方法来获取基于CusID和ServiceDate的先前值,以便我得到这样的结果:
CustID CustName ServiceDate PriorServiceDate
1 1 Fred 2010-11-01 <NA>
2 2 Maria 2008-03-25 <NA>
3 3 John 2007-03-14 <NA>
4 4 Mark 2010-11-01 <NA>
5 5 Julia 2008-03-25 2008-03-14
6 1 Fred 2010-12-14 2010-11-01
7 5 Julia 2008-03-14 <NA>
我尝试过使用sqldf但没有成功。谢谢。
答案 0 :(得分:4)
使用dplyr
我认为这可以解决您的问题。
library(dplyr)
df %>%
group_by(CustID) %>%
arrange(ServiceDate) %>%
mutate(PriorServiceDate = lag(ServiceDate))
Source: local data frame [7 x 4]
Groups: CustID
CustID CustName ServiceDate PriorServiceDate
1 1 Fred 2010-11-01 <NA>
2 1 Fred 2010-12-14 2010-11-01
3 2 Maria 2008-03-25 <NA>
4 3 John 2007-03-14 <NA>
5 4 Mark 2010-11-01 <NA>
6 5 Julia 2008-03-14 <NA>
7 5 Julia 2008-03-25 2008-03-14
请注意,这假设您使用lag
查看前一个日期,而不是最短日期(不确定您的问题)。
如果您确实想要min
,那么您可以轻松地将其他人编入索引
df2 <- df %>%
group_by(CustID) %>%
arrange(ServiceDate) %>%
mutate(PriorServiceDate = min(ServiceDate))
df2$PriorServiceDate[which(df2$ServiceDate == df2$PriorServiceDate)] = NA
Source: local data frame [7 x 4]
Groups: CustID
CustID CustName ServiceDate PriorServiceDate
1 1 Fred 2010-11-01 <NA>
2 1 Fred 2010-12-14 2010-11-01
3 2 Maria 2008-03-25 <NA>
4 3 John 2007-03-14 <NA>
5 4 Mark 2010-11-01 <NA>
6 5 Julia 2008-03-14 <NA>
7 5 Julia 2008-03-25 2008-03-14
答案 1 :(得分:2)
与dplyr
答案不同,它使用基数R并获得最小日期而不是滞后。
首先获得每位客户的第一个服务日期。
first.service <- with(df, aggregate(ServiceDate,
by=list(CustID=CustID, CustName=CustName),
FUN=min))
现在将其与原始数据框合并。
both <- merge(df, first.service, by=c("CustID", "CustName"))
对于没有此类服务的客户,您可以将之前的服务日期设置为NA
:
both$x[with(both, ServiceDate == x)] <- NA
然后重命名列:
colnames(both)[4] <- "PriorServiceDate"
答案 2 :(得分:1)
使用sqldf可以使用左自连接完成。对于来自b
的特定行,保留a
的行CustID
与来自CustID
的{{1}}相同且其b
更少。然后在那些ServiceDate
行中选择a
最大的行。这不会对输入的顺序做出任何假设。它保留了行的原始顺序,但如果这不重要,那么ServiceDate
行可以省略:
order by
,并提供:
library(sqldf)
DF <- sqldf("select b.CustID,
b.CustName,
b.ServiceDate ServiceDate__Date,
max(a.ServiceDate) PriorDate__Date
from df b
left join df a
on b.ServiceDate > a.ServiceDate and b.CustID = a.CUSTID
group by b.CustID, b.ServiceDate
order by b.rowid",
method = "name__class")