This solution only uses the base of R and retains the original order of the input:
# Sort, calculate differences and unsort.
# r is row indexes to use, order.by is ordering vector, col is vector to difference
diffs <- function(r, order.by, col) {
order.by <- order.by[r]
col <- col[r]
o <- order(order.by)
replace(r, o, c(NA, diff(col[o])))
}
# fun specialized to arguments after first, i.e. subsequent arguments curried
curry <- function (fun, ...) function(r) fun(r, ...)
ix <- 1:nrow(DF)
transform(DF,
days_since = ave(ix, customer, FUN = curry(diffs, date, date)),
amt_diff = ave(ix, customer, FUN = curry(diffs, date, purchase_amt))
)
The result is:
customer visit date purchase_amt days_since amt_diff
1 sarah 2 2013-08-09 5 19 -3
2 sarah 3 2013-07-21 8 28 -1
3 sarah 4 2013-06-23 9 21 8
4 sarah 5 2013-06-02 1 NA NA
5 sarah 1 2013-08-20 8 11 3
6 henry 1 2013-07-04 4 NA NA
7 che 1 2013-08-27 2 31 1
8 che 2 2013-07-27 1 22 -7
9 che 3 2013-07-05 8 21 5
10 che 4 2013-06-14 3 NA NA
11 dt 3 2013-04-05 9 NA NA
12 dt 2 2013-06-07 1 63 -8
13 dt 1 2013-07-11 6 34 5
UPDATE: minor improvements to code.