2013-01-21 7 views
5

devo andare da questoCome calcolare i giorni passati dalla data di inizio per gruppo?

id | date 
----------------- 
    A | 2000-01-13 
    A | 2000-01-18 
    A | 2000-01-25 
    B | 2012-10-10 
    B | 2012-10-11 
    C | 2005-07-25 
    C | 2005-07-31 

presente

id | date  | days from start 
--------------------------- 
    A | 2000-01-13 | 0 
    A | 2000-01-18 | 5 
    A | 2000-01-25 | 12 
    A | 2000-02-08 | 26 
    B | 2012-10-10 | 0 
    B | 2012-10-11 | 1 
    C | 2005-07-25 | 0 
    C | 2005-07-31 | 6 

cioè creando una variabile che contiene il numero di giorni trascorsi dalla prima data, raggruppati per id.

Qualche idea?

risposta

8

Utilizzando data.table: (presumo la colonna date è il carattere qui Se il suo formato date, allora si può rimuovere la chiamata as.Date(.) funzione di

df <- structure(list(id = c("A", "A", "A", "B", "B", "C", "C"), 
      date = c("2000-01-13", "2000-01-18", "2000-01-25", "2012-10-10", 
        "2012-10-11", "2005-07-25", "2005-07-31")), 
      .Names = c("id", "date"), row.names = c(NA, -7L), 
      class = "data.frame") 
require(data.table) 
dt <- data.table(df, key="id") 
dt[, days_from_start := cumsum(c(0, diff(as.Date(date)))),by=id] 

# id  date days_from_start 
# 1: A 2000-01-13    0 
# 2: A 2000-01-18    5 
# 3: A 2000-01-25    12 
# 4: B 2012-10-10    0 
# 5: B 2012-10-11    1 
# 6: C 2005-07-25    0 
# 7: C 2005-07-31    6 
+2

Quasi per pubblicare esattamente la stessa cosa! – A5C1D2H2I1M1N2O1R2T1

+0

Così quando provo la tua soluzione, ho ricevuto un errore che diceva che 'Combinare: = in j con by non è ancora stato implementato. Per favore lascia che il maintainer ('data.table') sappia se sei interessato a questo. È perché la mia versione di R è troppo vecchia (2.14.2) o la mia versione del pacchetto 'data.table' (1.8.0)? – plannapus

5

È anche possibile utilizzare una combinazione di funzioni difftime e split..:

dat 
    id  date 
1 A 2000-01-13 
2 A 2000-01-18 
3 A 2000-01-25 
4 B 2012-10-10 
5 B 2012-10-11 
6 C 2005-07-25 
7 C 2005-07-31 

dat$date <- as.POSIXct(dat$date) 
dat$"Days spent" <- unlist(lapply(split(dat,f=dat$id), 
         function(x){as.numeric(difftime(x$date,x$date[1], units="days"))})) 
dat 
    id  date Days spent 
1 A 2000-01-13   0 
2 A 2000-01-18   5 
3 A 2000-01-25   12 
4 B 2012-10-10   0 
5 B 2012-10-11   1 
6 C 2005-07-25   0 
7 C 2005-07-31   6 

seguenti suggerimenti @agstudy e @Arun, questo può essere semplificato come segue:

01.235.164,106174 millions altri
dat$"Days spent" <- unlist(by(dat, dat$id, 
          function(x)difftime(x$date,x$date[1], units= "days"))) 
+1

Ho usato 'difftime' qui perché non volevo una differenza ritardata ma la differenza tra ogni elemento e il primo. Altrimenti 'diff' è davvero molto adatto per le date (per quanto posso vedere comunque). – plannapus

+1

Potrei suggerire di sostituire lapply + split = per ... – agstudy

0

due approcci: ave e utilizzando la libreria plyr:

df <- 
structure(list(id = c("A", "A", "A", "B", "B", "C", "C"), date = structure(c(10969, 
10974, 10981, 15623, 15624, 12989, 12995), class = "Date")), .Names = c("id", 
"date"), row.names = c(NA, -7L), class = "data.frame") 

Utilizzando ave, la data deve essere cambiato a numerico

df$days_from_start <- ave(as.numeric(df$date), df$id, FUN = function(x) x-min(x)) 

che dà

> df 
    id  date days_from_start 
1 A 2000-01-13    0 
2 A 2000-01-18    5 
3 A 2000-01-25    12 
4 B 2012-10-10    0 
5 B 2012-10-11    1 
6 C 2005-07-25    0 
7 C 2005-07-31    6 
> str(df) 
'data.frame': 7 obs. of 3 variables: 
$ id    : chr "A" "A" "A" "B" ... 
$ date   : Date, format: "2000-01-13" ... 
$ days_from_start: num 0 5 12 0 1 0 6 

Noi ing biblioteca plyr:

library("plyr") 
df <- ddply(df, .(id), mutate, days_from_start = date - min(date)) 

che dà

> df 
    id  date days_from_start 
1 A 2000-01-13   0 days 
2 A 2000-01-18   5 days 
3 A 2000-01-25   12 days 
4 B 2012-10-10   0 days 
5 B 2012-10-11   1 days 
6 C 2005-07-25   0 days 
7 C 2005-07-31   6 days 
> str(df) 
'data.frame': 7 obs. of 3 variables: 
$ id    : chr "A" "A" "A" "B" ... 
$ date   : Date, format: "2000-01-13" ... 
$ days_from_start:Class 'difftime' atomic [1:7] 0 5 12 0 1 0 6 
    .. ..- attr(*, "units")= chr "days" 
Problemi correlati