2013-07-18 2 views
0

입니다. 특정 이벤트 간의 날짜 차이를 계산하는 데 많은 시간을 할애했습니다. 예를 들어, 아래에 설정된 데이터가 있습니다. 여기서 t는 이벤트 datetime이고, e는 이벤트 ('A'또는 'R')이고 id는 식별자입니다.특정 이벤트 간의 날짜 차이가 R

 
t     e id 
2013-06-15 20:59:17 A 086 
2013-06-26 18:02:09 R 086 
2013-06-27 03:17:07 A 086 
2013-06-01 11:34:09 R 115 
2013-06-16 19:59:08 R 522 
2013-06-16 20:05:04 R 522 
2013-06-07 09:31:15 A 524 
2013-06-09 16:24:04 R 524 
2013-06-14 03:38:09 A 524 
2013-06-16 15:49:09 R 524 
2013-06-21 03:54:19 A 524 
2013-06-12 12:34:37 A 638 
2013-06-12 13:15:27 A 638 
2013-06-15 16:12:23 R 638 
2013-06-18 22:05:03 A 638 
2013-06-28 13:30:20 R 638 
2013-06-28 22:20:12 A 638 
2013-06-01 18:34:46 A 836 
2013-06-01 18:44:53 A 836 
2013-06-03 14:35:09 R 836 
2013-06-03 20:25:51 A 836 
2013-06-03 20:27:25 A 836 
2013-06-03 20:32:17 A 836 
2013-06-08 16:22:07 R 836 
2013-06-12 13:12:21 A 836 
2013-06-12 13:15:16 A 836 
2013-06-12 13:18:53 A 836 
2013-06-12 18:59:24 A 836 
2013-06-23 21:14:12 R 836 
2013-06-24 20:16:11 R 836 
2013-06-25 03:34:29 A 836 
2013-06-26 20:33:11 R 836 

각 ID, 나는이 'A'이벤트와 'R'이벤트 사이 (일) 날짜 시간 차이가있을 것입니다, 새로운 데이터 세트를 만들 하시겠습니까.

각 id에 대해 : E 이전에 이벤트가 없으면 아무 것도 계산하지 않습니다. 첫 번째 이벤트 A와 첫 번째 이벤트 E가있는 diff 일을 계산하려면 두 이벤트 이전에 세 개의 이벤트 A가있는 경우 이벤트 A 또는 E 만 있으면 아무 것도 계산하지 않습니다. 그런 다음 id = 086, 115, 638에 대해이 duples (id, days) (086, 10.9) (638, 3.2) (638, 9.6)을 얻고 싶습니다. id = 115가 나타나지 않거나 NaN 일 수 있습니다. 단 하나의 이벤트 R과 이벤트 A가 없습니다.

 
id days 
086 10.9 (Ex. 2013-06-26 18:02:09 - 2013-06-15 20:59:17) 
524 2.3 
524 2.5 
638 3.2 
638 9.6 
836 1.8 
836 4.8 (Ex. 2013-06-08 16:22:07 - 2013-06-03 20:25:51) 
836 11.3 
836 1.7 

나는 첫 번째 방법으로이 코드를 사용하고 있습니다 :

집계 (as.POSIXct (안양 $의 t), 목록 (안양 $ 아이디), 차이)에 관한

어떤 아이디어 어떻게해야합니까? 미리 감사드립니다.

dataframe의 dput이다 : 여기서

 
> dput(df) 
structure(list(t = c("2013-06-15 20:59:17", "2013-06-26 18:02:09", 
"2013-06-27 03:17:07", "2013-06-01 11:34:09", "2013-06-16 19:59:08", 
"2013-06-16 20:05:04", "2013-06-07 09:31:15", "2013-06-09 16:24:04", 
"2013-06-14 03:38:09", "2013-06-16 15:49:09", "2013-06-21 03:54:19", 
"2013-06-12 12:34:37", "2013-06-12 13:15:27", "2013-06-15 16:12:23", 
"2013-06-18 22:05:03", "2013-06-28 13:30:20", "2013-06-28 22:20:12", 
"2013-06-01 18:34:46", "2013-06-01 18:44:53", "2013-06-03 14:35:09", 
"2013-06-03 20:25:51", "2013-06-03 20:27:25", "2013-06-03 20:32:17", 
"2013-06-08 16:22:07", "2013-06-12 13:12:21", "2013-06-12 13:15:16", 
"2013-06-12 13:18:53", "2013-06-12 18:59:24", "2013-06-23 21:14:12", 
"2013-06-24 20:16:11", "2013-06-25 03:34:29", "2013-06-26 20:33:11" 
), e = c("A", "R", "A", "R", "R", "R", "A", "R", "A", "R", "A", 
"A", "A", "R", "A", "R", "A", "A", "A", "R", "A", "A", "A", "R", 
"A", "A", "A", "A", "R", "R", "A", "R"), id = c("086", "086", 
"086", "115", "522", "522", "524", "524", "524", "524", "524", 
"638", "638", "638", "638", "638", "638", "836", "836", "836", 
"836", "836", "836", "836", "836", "836", "836", "836", "836", 
"836", "836", "836")), .Names = c("t", "e", "id"), row.names = c(855945L, 
1481100L, 1508045L, 16944L, 920490L, 921005L, 349201L, 494172L, 
746450L, 904442L, 1163757L, 653045L, 654357L, 834901L, 1047932L, 
1583218L, 1613753L, 36421L, 37178L, 139968L, 162274L, 162417L, 
162804L, 430725L, 654254L, 654350L, 654453L, 670726L, 1333676L, 
1384583L, 1401293L, 1491782L), class = "data.frame") 
+0

데이터를 입력 할 수 있도록 데이터를 입력 할 수 있습니까? –

+0

@JakeBurkhead : 추가했습니다. 감사! – MSS

+0

출력 결과에 따라 주어진 ID에 대해 여러 시간이 표시되는 경우가 있습니다. 이것이 "첫 번째 이벤트에서 첫 번째 이벤트"에 어떻게 맞습니까? –

답변

3

plyr 패키지에서 ddply 기능과 날짜를 파싱하는 lubridate 패키지를 사용하여 한 라인의 솔루션이다.

번호 :

library(plyr) 
library(lubridate) 

new_df <- ddply(.data=df, .variables=c('id'), summarize, 
       days=round(ymd_hms(t[match('R',e)])-ymd_hms(t[match('A',e)]),1)) 
new_df 

출력 : id S (115) 및 (522)는 e 변수 값을 가지지 않기 때문에 2 경고가 있는지

id  days 
1 086 10.9 days 
2 115 NA days 
3 522 NA days 
4 524 2.3 days 
5 638 3.2 days 
6 836 1.8 days 

참고. 10 진수 값으로 날짜의 차이를 원한다면

, 당신은 지금처럼 as.double 기능을 사용할 수 있습니다 :

을 기본적으로, 나는 AR의 첫 번째 항목을 찾을 수 match 기능을 사용하고는 구문 분석 lubridate 패키지의 ymd_hms 함수를 사용하여 날짜 변수를 찾은 다음 두 날짜의 차이점을 찾습니다. 소수점 1 자리로 반올림 한 다음 double으로 변환하여 표시합니다.

편집

작전 코멘트를 읽은 후, 여기에 원하는 결과를 얻을 수있는 오히려 추한 방법입니다. 용서하십시오, 그것은 아침 일찍이며, 우아하지 않거나 효율적이지는 않지만 원하는 결과를 출력하는 것으로 보입니다.

코드 :

grouper <- function(var, group) { 
    num <- 1 
    res <- c(1:length(var)) 
    for(i in 1:length(var)) { 
    res[i] <- num 
    if(var[i]==group) { 
     num <- num+1 
    } 
    } 
    return(res) 
} 

df2 <- df 
df2$group <- ddply(.data=df, .variables='id', summarize, group=grouper(e,'R'))$group 

df3 <- ddply(.data=df2, .variables=c('id','group'), summarize, 
      days=round(ymd_hms(t[match('R',e)])-ymd_hms(t[match('A',e)]),1)) 

df3[complete.cases(df3),-2] 

출력 :

id  days 
1 086 10.9 days 
6 524 2.3 days 
7 524 2.5 days 
9 638 3.2 days 
10 638 9.6 days 
12 836 1.8 days 
13 836 4.8 days 
14 836 11.3 days 
16 836 1.7 days 
아이디어는 내가 데이터를 부분 집합 할 수 있도록한다는 'R'이벤트의 발생에 의해 그룹 행을 다른 열을 추가하는 것입니다

ID와 'R'이벤트 둘 다에 의해 설정됩니다. 그것은 일종의 해커 다. 그리고 나는 그것을하는 더 우아한 방법이있을 것이라고 확신한다.

지금, 나는 커피를 사러 나서.

+0

감사. ID 524는 2 회 (2.3 및 2.5 일) 나타나야하고 1 회 (2.3 일) 표시되기 때문에 부분적으로 작동합니다. 내 뜻 2013-06-09 16:24:04 - 2013-06-07 09:31:15 = 2.3 및 2013-06-16 15:49:09 - 2013-06-14 03:38:09 = 2.5 – MSS

+0

음 알았어. 질문을 읽을 때 첫 번째 R 이벤트와 각 ID에 대한 첫 번째 A 이벤트의 차이 만 원한다고 생각했습니다. – ialm

+0

@MSV 내 편집을 확인하십시오! – ialm

2

여기에 한 가지 방법

df <- transform(df, t=as.POSIXct(t)) 
sp <- split(df, df$id) 
calc_diff <- function(x) { 
    start <- min(subset(x, e=="A")$t) 
    end <- min(subset(x, e=="R")$t) 
    return(end-start) 
} 
sapply(sp, FUN=calc_diff) 
+0

감사. 이전 코드와 동일하게 발생합니다. ID 524는 2 회 (2.3 및 2.5 일) 나타나야하고 1 회 (2.3 일) 표시되기 때문에 부분적으로 작동합니다. 나는 뜻합니다 2013-06-09 16:24:04 - 2013-06-07 09:31:15 = 2.3 및 2013-06-16 15:49:09 - 2013-06-14 03:38:09 = 2.5 – MSS

+0

아마도 여러분의 필요에 맞게'calc_diff' 함수를 변경할 수 있습니다. 나는 아직도 당신의 필요를 이해하는 데 어려움을 겪고 있으며 다른 독자들에게 유용하기에는 너무 전문화되어 있다고 생각합니다. –

3

아무것도 필요가 없습니다,하지만 기본 R. 주문 귀하의 data.frame, 당신의 "첫 번째"출연을 선택하고 마지막으로 당신이 무엇을 사용에 집계 유사한을 사용

df <- df[do.call(order, df), ] 
df <- df[!duplicated(df[, c("id", "e")]), ] 
tdiff <- function(x) { 
    if(length(x) == 2) { 
    rv <- as.numeric(difftime(strptime(x[2], format="%Y-%m-%d %H:%M:%S"), 
           strptime(x[1], format="%Y-%m-%d %H:%M:%S"), 
           units = "days")) 
    } else { 
    rv <- NA 
    } 
    rv 
} 

rv <- aggregate(df$t, by = list(id = df$id), tdiff) 

더 이상 필요 없으므로 폐쇄만을 위해 원하는 방식으로 작동하는 버전이 있습니다.

df <- df[do.call(order, df), ] 
df_a <- subset(df, e == "A") 
df_a <- df_a[!duplicated(df_a[, c("id", "e")]), ] 
df_r <- subset(df, e == "R") 
df_r[, 'A'] <- df_a[match(df_r$id, df_a$id), 't'] 
df_r[, 'R_A'] <- as.numeric(difftime(strptime(df_r[, 't'], format="%Y-%m-%d %H:%M:%S"), 
          strptime(df_r[, 'A'], format="%Y-%m-%d %H:%M:%S"), 
          units = "days")) 
rv <- df_r[, c('id', 'R_A')] 
rv[!is.na(rv$R_A) & rv$R_A < 0, 'R_A'] <- NA 
rv <- rv[!duplicated(rv), ] 
+0

df $ t의 오류 : 원자 벡터에 $ 연산자가 유효하지 않습니다. – MSS

+0

오류가있어 작동하지 않습니다. – MSS

+0

@MSV, 오류가 발생했습니다. 나는 내가 쓴 것을 시험하기 위해 R에 접근했다. 내가 입력 할 때 수정 프로그램이 나옵니다. –