2013-01-21 23 views
5

Ben kimliğiyle gruplandırılmış ilk tarihten bu yana geçen gün sayısını tutan bir değişken oluşturma buBaşlama tarihinden gruptan geçen günler nasıl hesaplanır?

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 

yani bu

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 

gitmek gerekir.

Herhangi bir fikrin var mı? data.table kullanma

cevap

8

: (ı date kolon karakteri burada olduğunu varsayalım onun date biçimi, o zaman as.Date(.) işlev çağrısını kaldırabilir

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
+0

Çözümünüzü denediğimde, 'Combining: = ile j ile henüz uygulanmadığını söyleyen bir hata aldım. Bu konuyla ilgileniyorsanız lütfen bunu ('data.table') sürdürün. Bunun nedeni R sürümümün çok eski (2.14.2) veya 'data.table' (1.8.0) paket sürümüm olması mı? – plannapus

5

Ayrıca fonksiyonlar difftime ve split bir arada kullanabilirsiniz..: aşağıdaki gibi @agstudy ve @Arun önerileri takiben

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 

, bu kolaylaştırılabilir:

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

Burada 'difftime' kullandım çünkü gecikmeli bir fark istemedim, ancak her bir element ile birincisi arasındaki fark. Aksi taktirde, 'diff' aslında tarihler için çok uygundur (zaten görebildiğim kadarıyla). – plannapus

+1

lapply + split = ile değiştirmeyi önerebilir miyim? – agstudy

0

Diğer iki yaklaşımlar: ave ve plyr kitaplığı kullanarak: ave kullanma

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") 

, tarih

> 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 

veren sayısal

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

şekilde değiştirilmelidir Bize plyr kütüphane ing:

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

hangi tam olarak aynı şeyi yayınlamak üzereydim

> 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"