R-如何同时使用diff()和分组?

时间:2015-02-12 08:36:41

标签: r

我有一个值为

的数据框
cust_no name    trans_date     amount
1122    abc     2014-03-10     2000
1122    abc     2014-03-15     300
4444    pqr     2014-01-10     1000
4444    pqr     2014-01-15     1000
4444    pqr     2014-02-15     1000
7777    xyz     2014-01-10     34
7777    xyz     2014-01-11     444
7777    xyz     2014-01-17     2344
7777    xyz     2014-01-30     345

我希望计算相同客户的两笔交易之间的天差。我的输出应该像

cust_no name  trans_date       amount TimeDiff    
1122     abc 2014-03-10         2000  0
1122     abc 2014-03-15         300   5
4444     pqr 2014-01-10         1000  0
4444     pqr 2014-01-15         1000  5
4444     pqr 2014-02-15         1000  30
7777     xyz 2014-01-10         34    0
7777     xyz 2014-01-11         444   1
7777     xyz 2014-01-17         2344  6
7777     xyz 2014-01-30         345   13

我尝试了以下代码(当然不使用diff()

> for( i in 1:(nrow(df)-1)){
+   if(ds$cust_no[i]==ds$cust_no[i+1]){
+     ds$TimeGap[i]<-ds$trans_Date[i+1]-ds$trans_Date[i]
+   }
+ }

但是我没有得到如上所示的所需输出。相反,我得到下面的一个,它基本上计算表的transaction_date的每个值之间的时间间隔,这从负值可以看出。

1122 abc 2014-03-10 2000  0
1122 abc 2014-03-15 300   5
4444 pqr 2014-01-10 1000  -64
4444 pqr 2014-01-15 1000  5
4444 pqr 2014-02-15 1000  30
7777 xyz 2014-01-10 34    -35
7777 xyz 2014-01-11 444   1
7777 xyz 2014-01-17 2344  6
7777 xyz 2014-01-30 345   13

1 个答案:

答案 0 :(得分:3)

您可以使用ave或包dplyrdata.table按组计算。

数据

df <- structure(list(cust_no = c(1122L, 1122L, 4444L, 4444L, 4444L, 
7777L, 7777L, 7777L, 7777L), name = structure(c(1L, 1L, 2L, 2L, 
2L, 3L, 3L, 3L, 3L), .Label = c("abc", "pqr", "xyz"), class = "factor"), 
    trans_date = structure(c(16139, 16144, 16080, 16085, 16116, 
    16080, 16081, 16087, 16100), class = "Date"), amount = c(2000L, 
    300L, 1000L, 1000L, 1000L, 34L, 444L, 2344L, 345L)), .Names = c("cust_no", 
"name", "trans_date", "amount"), row.names = c(NA, -9L), class = "data.frame")

基础解决方案(来自@akrun)

df$time_diff <- with(df, ave(as.numeric(trans_date), cust_no, FUN=function(x) c(0, diff(x))))

dplyr解决方案

require(dplyr)
df %>% group_by(cust_no) %>% mutate(time_diff = c(0, diff(trans_date)))

data.table解决方案

require(data.table)
setDT(df)[, time_diff :=c(0, diff(trans_date)), by=cust_no][]