2015-10-16 2 views
2

Je veux ajouter une colonne indiquant la différence de données entre m+1 -th col . de n -ième rangée et m -th col. de n+1 -th rangée.R: différence de date entre (m + 1) -ième colonne de n-ème ligne et m-ème colonne de (n + 1) -ième rangée

Le format de données est aussi df,

set.seed(2) 
user.list = c('A','B','C') 
t = seq(as.Date("2015/1/1"), as.Date("2015/12/31"), 'days') 
st = sort(sample(t, 10)) 
et = st+30 
df = data.frame(
     user=sort(sample(user.list, 10, replace=T)), 
     start=st, 
     due=et 
    ) 

Le résultat attendu devrait être

user  start  due  td 
1  A 2015-02-16 2015-03-18 -16 
2  A 2015-03-02 2015-04-01 -23 
3  A 2015-03-09 2015-04-08  70 
4  A 2015-06-17 2015-07-17 197* 
5  B 2015-07-15 2015-08-14 -17 
6  B 2015-07-28 2015-08-27  17 
7  B 2015-09-13 2015-10-13 109* 
8  C 2015-10-26 2015-11-25  11 
9  C 2015-12-06 2016-01-05 -29 
10 C 2015-12-07 2016-01-06  24* 

avec td indiquant la différence de temps en unité de jour. Par exemple, pour l'utilisateur A, -16 est dérivé de la différence entre 2015-03-02 et 2015-03-18; -23 est la différence entre 2015-03-09 et 2015-04-01, etc. Le numéro avec * est la dernière ligne de chaque utilisateur, qui est dérivée alternativement de la différence entre une date fixe 2016-01-30 et 2015 -07-17 (pour l'utilisateur A).

Comment peut-il être résolu par un moyen efficace sans dlply (diviser en liste d'utilisateurs), et forif (balayage de chaque ligne et voir si elle est la dernière de l'utilisateur)?

Répondre

2

Avec dplyr:

library(dplyr) 
df %>% group_by(user) %>% 
    mutate(start = c(start, as.Date("2016-01-30"))[-1]) %>% 
    mutate(td = start - due) 
# Source: local data frame [10 x 4] 
# Groups: user [3] 
# 
#  user  start  due  td 
# (fctr)  (date)  (date) (dfft) 
# 1  A 2015-03-02 2015-03-18 -16 days 
# 2  A 2015-03-09 2015-04-01 -23 days 
# 3  A 2015-06-17 2015-04-08 70 days 
# 4  A 2016-01-30 2015-07-17 197 days 
# 5  B 2015-07-28 2015-08-14 -17 days 
# 6  B 2015-09-13 2015-08-27 17 days 
# 7  B 2016-01-30 2015-10-13 109 days 
# 8  C 2015-12-06 2015-11-25 11 days 
# 9  C 2015-12-07 2016-01-05 -29 days 
# 10  C 2016-01-30 2016-01-06 24 days 

Si vous voulez coller avec base R, quelque chose de similaire:

start <- ave(df$start, df$user, FUN=function(x) c(x, as.Date("2016-01-30"))[-1]) 
df$td <- start - df$due 

Si vous voulez faire des choses comme ajouter des étoiles et sortir l'unité « jours », vous pouvez ajuster en conséquence. (c'est-à-dire sub(" .*", "", df$td))