2013-01-21 37 views
5

Tôi cần phải đi từ nàyCách tính số ngày được chuyển từ ngày bắt đầu theo nhóm?

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 

này

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 

ví dụ: tạo một biến chứa số ngày trôi qua kể từ ngày đầu tiên, nhóm lại theo id.

Bất kỳ ý tưởng nào?

Trả lời

8

Sử dụng data.table: (tôi giả sử cột date là nhân vật ở đây Nếu định dạng date của nó, sau đó bạn có thể loại bỏ các cuộc gọi as.Date(.) chức năng

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

Chỉ cần về để gửi chính xác những điều tương tự! – A5C1D2H2I1M1N2O1R2T1

+0

Vì vậy, khi tôi thử giải pháp của bạn, tôi nhận được một lỗi nói rằng 'Kết hợp: = trong j với bởi chưa được triển khai. Vui lòng cho người duy trì ('data.table') biết nếu bạn quan tâm đến điều này.'. Có phải vì phiên bản R của tôi quá cũ (2.14.2) hoặc phiên bản gói 'data.table' (1.8.0) của tôi không? – plannapus

5

Bạn cũng có thể sử dụng một sự kết hợp của các chức năng difftimesplit..:

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 

Tiếp theo gợi ý @agstudy và @Arun, điều này có thể được đơn giản hóa như sau:

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

Tôi đã sử dụng 'difftime' ở đây vì tôi không muốn có sự khác biệt về độ trễ nhưng sự khác biệt giữa mỗi phần tử và phần tử đầu tiên. Nếu không 'diff' thực sự là rất phù hợp cho ngày (như xa như tôi có thể nhìn thấy anyway). – plannapus

+1

Tôi có thể đề xuất thay thế lapply + split = theo ... – agstudy

0

Hai cách tiếp cận khác: ave và sử dụng plyr thư viện:

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

Sử dụng ave, ngày phải được thay đổi để số

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

mang đến cho

> 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 

Hệ ing thư viện plyr:

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

mang đến cho

> 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" 
Các vấn đề liên quan