2017-11-09 2 views
0

병원 입원 중 환자의 위치를 ​​유지하는 데이터 프레임을 사용하고 있습니다. 해당 행 (= ID)에 대한 특정 기간 (BeginTim에서 EndTime까지) 동안 새로운 위치 (= 부서, 방, 침대)를 나타내는 방식으로 형식이 지정됩니다.데이터 프레임을 기간별 행에서 일일 행으로 변환

다음은 초기 데이터 프레임의 샘플입니다 :

print(data_perlocation[1:10,]) 
    ID  department  BeginTime      EndTime    room Bed 
    <dbl>  <chr>   <chr>      <chr>    <dbl> <dbl> 
1 2156864  L14B 2016-03-02 09:40:00.0000000 2016-03-02 15:20:00.0000000 102  3 
2 2161034  B51A 2016-06-07 00:00:00.0000000 2016-06-07 11:02:00.0000000 109  2 
3 2161034  B51A 2016-06-06 09:00:00.0000000 2016-06-06 10:27:00.0000000 109  2 
4 2161034  B51A 2016-06-06 12:47:00.0000000 2016-06-07 00:00:00.0000000 109  2 
5 2161034  B51A 2016-06-06 10:27:00.0000000 2016-06-06 12:47:00.0000000 103  3 
6 2176442  L14B 2016-02-04 07:15:00.0000000 2016-02-04 13:47:00.0000000 101  4 
7 2176754  B61A 2016-03-15 07:16:00.0000000 2016-03-15 14:56:00.0000000 109  3 
8 2176754  B61A 2016-03-16 08:10:00.0000000 2016-03-17 00:00:00.0000000 109  3 
9 2176754  B61A 2016-03-15 14:56:00.0000000 2016-03-16 08:10:00.0000000 109  2 
10 2176754  B61A 2016-03-17 00:00:00.0000000 2016-03-17 11:18:00.0000000 109  3 
11 2184060  B61A 2016-03-10 20:25:00.0000000 2016-03-11 00:00:00.0000000 105  2 
12 2184060  B61A 2016-03-10 20:01:00.0000000 2016-03-10 20:25:00.0000000 105  1 
13 2184060  B61A 2016-03-11 00:00:00.0000000 2016-03-12 00:00:00.0000000 105  2 
14 2184060  B61A 2016-03-12 00:00:00.0000000 2016-03-12 14:00:00.0000000 105  2 

는 내가 매일 행을해야합니다 있도록이 데이터 프레임을 변환 할. 따라서 ID와 입학 날짜가있는 열이있는 새 데이터 프레임을 만들었습니다. 이처럼 :

ID  Date 
1 2156864 2016-03-02 
2 2161034 2016-06-06 
3 2161034 2016-06-07 
4 2176442 2016-02-04 
5 2176754 2016-03-15 
6 2176754 2016-03-16 
7 2176754 2016-03-17 
8 2184060 2016-03-10 
9 2184060 2016-03-11 
10 2184060 2016-03-12 

는 지금은 ID 일치 어디서 beginDate 날짜와 일치와 data_byday 행으로 data_bylocation 데이터 프레임에 존재하는 하루 (다중) 위치 (들)을 추가 할.

for와 if 문을 결합했습니다. 지금까지의 시도는 원하는 결과에 가까운 것을 제공하지 못했고, 나는이 일을 훨씬 쉽게 할 수있는 방법이라고 생각합니다. 여전히 학습,

ID  Date  BeginTime1 EndTime1 department1 room1 bed1  BeginTime2 EndTime2 department2 room2 bed2 [3rd location, etc] 
1 2156864 2016-03-02    [first location of this day]      [second location of this day] 
2 2161034 2016-06-06 
3 2161034 2016-06-07 
4 2176442 2016-02-04 
5 2176754 2016-03-15 
6 2176754 2016-03-16 
7 2176754 2016-03-17 
8 2184060 2016-03-10 
9 2184060 2016-03-11 
10 2184060 2016-03-12 

내가 R에 아주 새로운 해요 :

data_perday[,3] <- NA 
for (index in 1:nrow(data_perlocation)){ 
    if (data_perlocation$ID[index]==data_perday$ID & as.Date(as.character(data_perlocation$BeginTime[index]), format="%Y-%m-%d")==as.Date(data_perday$Date, format="%Y-%m-%d")) { 
    if (is.na(data_perday[index,3])){   
    ##code to assign location and time of for that day 
} else { 
    ##code to assign second location and time of for that day and place 
     }}} 

원하는 결과는 다음과 같은 : 내 마지막 시도는 다음과 같이 끝났다. 나는이 문제에 잠시 붙어 있었다. 그래서 올바른 방향으로 어떤 조언을 많이 주시면 감사하겠습니다!

EDIT :

재현 예 :

data_byday <- structure(list(ID = c(2156864, 2161034, 2161034, 2176442, 2176754, 2176754, 2176754, 2184060, 2184060, 2184060), Date = c("2016-03-02", "2016-06-06", "2016-06-07", "2016-02-04", "2016-03-15", "2016-03-16", "2016-03-17", "2016-03-10", "2016-03-11", "2016-03-12")), .Names = c("ID", "Date"), row.names = c(NA, 10L), class = "data.frame") 


data_bylocation <- structure(list(ID = c(2156864, 2161034, 2161034, 2161034, 2161034, 2176442, 2176754, 2176754, 2176754, 2176754, 2184060, 2184060, 2184060, 2184060), department = c("L14B", "B51A", "B51A", "B51A", "B51A", "L14B", "B61A", "B61A", "B61A", "B61A", "B61A", "B61A", "B61A", "B61A"), BeginTime = c("2016-03-02 09:40:00.0000000", "2016-06-07 00:00:00.0000000", "2016-06-06 09:00:00.0000000", "2016-06-06 12:47:00.0000000", "2016-06-06 10:27:00.0000000", "2016-02-04 07:15:00.0000000", "2016-03-15 07:16:00.0000000", "2016-03-16 08:10:00.0000000", "2016-03-15 14:56:00.0000000", "2016-03-17 00:00:00.0000000", "2016-03-10 20:25:00.0000000", "2016-03-10 20:01:00.0000000", "2016-03-11 00:00:00.0000000", "2016-03-12 00:00:00.0000000"), EndTime = c("2016-03-02 15:20:00.0000000", "2016-06-07 11:02:00.0000000", "2016-06-06 10:27:00.0000000", "2016-06-07 00:00:00.0000000", "2016-06-06 12:47:00.0000000", "2016-02-04 13:47:00.0000000", "2016-03-15 14:56:00.0000000", "2016-03-17 00:00:00.0000000", "2016-03-16 08:10:00.0000000", "2016-03-17 11:18:00.0000000", "2016-03-11 00:00:00.0000000", "2016-03-10 20:25:00.0000000", "2016-03-12 00:00:00.0000000", "2016-03-12 14:00:00.0000000"), room = c(102, 109, 109, 109, 103, 101, 109, 109, 109, 109, 105, 105, 105, 105), Bed = c(3, 2, 2, 2, 3, 4, 3, 3, 2, 3, 2, 1, 2, 2)), .Names = c("ID", "department", "BeginTime", "EndTime", "room", "Bed"), row.names = c(NA, -14L), class = c("tbl_df", "tbl", "data.frame")) 

번째 예 :

library(dplyr) 
library(tidyr) 
library(lubridate) 

data_bylocation %>% 
    mutate(Date = date(BeginTime)) %>% 
    gather(variable, value, -ID, -Date) %>% 
    group_by(ID, Date, temp = variable) %>% 
    mutate(index = row_number(), 
     variable = paste0(variable, index)) %>% 
    ungroup() %>% 
    select(-(temp:index)) %>% 
    spread(variable, value) %>% 
    select(ID, Date, c(6, 12, 9, 15, 3), c(6, 12, 9, 15, 3)+1, c(6, 12, 9, 15, 3)+2) 
: 여기
data_bylocation2 <- structure(list(ID = c(2224003, 2224003, 2224003, 2248787, 2248787,2248787, 2248787, 2248787), department = c("B12A", "B12A", "B12A","B53A", "B53A", "B53A", "B53A", "B53A"), BeginTime = c("2016-02-12 08:00:00.0000000", "2016-02-12 13:40:00.0000000", "2016-02-15 00:00:00.0000000", "2016-04-20 10:00:00.0000000", "2016-04-22 00:00:00.0000000", "2016-04-23 00:00:00.0000000", "2016-04-24 11:47:00.0000000", "2016-04-26 00:00:00.0000000"), EndTime = c("2016-02-12 13:40:00.0000000", "2016-02-15 00:00:00.0000000", "2016-02-15 16:17:00.0000000", "2016-04-22 00:00:00.0000000", "2016-04-23 00:00:00.0000000", "2016-04-24 11:47:00.0000000", "2016-04-26 00:00:00.0000000", "2016-04-26 16:00:00.0000000"), room = c(205, 209, 209, 306, 306, 306, 311, 311), bed = c(3, 1, 1, 2, 2, 2, 4, 4)), .Names = c("ID", "department", "BeginTime", "EndTime", "room", "bed"), row.names = c(NA, -8L), class = c("tbl_df", "tbl", "data.frame")) 
+0

왜 당신은 당신이 당신의 입력에 필요가 없습니다 당신의 예상 출력 개월/일을해야합니까? – useR

+0

실제로 큰 데이터 프레임에서 두 개의 다른 샘플을 게시했습니다. ID를 편집하여 샘플의 ID가 일치하도록했습니다. – FtD

+0

은 data.tables dcast가있는 하나의 라이너처럼 보이지만 직접 데이터를 복사하는 것은 게을리니다. "data <- data.frame (x = 1 : 10, y = 11)"형식으로 재현 가능한 예제를 제공 할 수 있습니까? : 20) "이걸 확인하기 위해 붙여 넣기를 복사 할 수 있습니까? 또는 "data

답변

0

OP는 특정 위치에서 하루 이상 머문 경우에도 환자의 위치를 ​​일 단위로 도표화하도록 요청했습니다.

이렇게하면 더 긴 체류 시간을 최대 1 시간으로 분할해야합니다. 이것은 foverlaps() 함수로 수행 할 수 있습니다. 넓은 형식에서 긴 형식으로 재 형성하려면 data.table::dcast() ~ 의 기능을 여러 열을 동시에 바꿔서이 사용됩니다.

library(data.table) 
# coerce time columns to POSIXct 
cols <- c("BeginTime", "EndTime") 
setDT(data_bylocation2)[, (cols) := lapply(.SD, as.POSIXct), .SDcols = cols] 

# create sequence of days which cover the whole period 
time_seq <- data_bylocation2[, seq(lubridate::floor_date(min(BeginTime), "day"), 
            lubridate::ceiling_date(max(EndTime), "day"), 
            by = "days")] 
# chop longer stays into one day chunks 
mDT <- foverlaps(data.table(Date = head(time_seq, -1L), end = tail(time_seq, -1L)), 
       setkey(data_bylocation2, BeginTime, EndTime), by.x = c("Date", "end"), nomatch = 0L)[ 
        , (cols) := .(pmax(BeginTime, Date), pmin(EndTime, end))][ 
        EndTime > BeginTime][ 
        order(ID, Date, BeginTime)] 

# reshape from long to wide form 
val_cols <- c("BeginTime", "EndTime", "department", "room", "bed") 
dcast(mDT, ID + Date ~ rowid(ID, Date), value.var = val_cols)[ 
    # reorder columns 
    , setcolorder(.SD, c("ID", "Date", 
         # create create column names in expected order using a cross join 
         mDT[, CJ(seq_len(max(rowid(ID, Date))), val_cols)[ 
         , paste(V2, V1, sep = "_")]]))] 
  ID  Date   BeginTime_1   EndTime_1 bed_1 department_1 room_1   BeginTime_2 EndTime_2 bed_2 department_2 room_2 
1: 2224003 2016-02-12 2016-02-12 08:00:00 2016-02-12 13:40:00  3   B12A 205 2016-02-12 13:40:00 2016-02-13  1   B12A 209 
2: 2224003 2016-02-13 2016-02-13 00:00:00 2016-02-14 00:00:00  1   B12A 209    <NA>  <NA> NA   NA  NA 
3: 2224003 2016-02-14 2016-02-14 00:00:00 2016-02-15 00:00:00  1   B12A 209    <NA>  <NA> NA   NA  NA 
4: 2224003 2016-02-15 2016-02-15 00:00:00 2016-02-15 16:17:00  1   B12A 209    <NA>  <NA> NA   NA  NA 
5: 2248787 2016-04-20 2016-04-20 10:00:00 2016-04-21 00:00:00  2   B53A 306    <NA>  <NA> NA   NA  NA 
6: 2248787 2016-04-21 2016-04-21 00:00:00 2016-04-22 00:00:00  2   B53A 306    <NA>  <NA> NA   NA  NA 
7: 2248787 2016-04-22 2016-04-22 00:00:00 2016-04-23 00:00:00  2   B53A 306    <NA>  <NA> NA   NA  NA 
8: 2248787 2016-04-23 2016-04-23 00:00:00 2016-04-24 00:00:00  2   B53A 306    <NA>  <NA> NA   NA  NA 
9: 2248787 2016-04-24 2016-04-24 00:00:00 2016-04-24 11:47:00  2   B53A 306 2016-04-24 11:47:00 2016-04-25  4   B53A 311 
10: 2248787 2016-04-25 2016-04-25 00:00:00 2016-04-26 00:00:00  4   B53A 311    <NA>  <NA> NA   NA  NA 
11: 2248787 2016-04-26 2016-04-26 00:00:00 2016-04-26 16:00:00  4   B53A 311    <NA>  <NA> NA   NA  NA 
+0

정말 고마워요! 이것은 내가 필요한 것입니다. 코멘트는 또한, 그래서 나는 무슨 일이 일어나고 있는지 이해할 수있다. – FtD

1

tidyverselubridate와 해결책

data.table으로 :

library(data.table) 
data = setDT(data_bylocation) 

newDT = dcast(melt(data[, date := lubridate::date(BeginTime)], 
        id.vars = c("ID", "date"))[ 
        ,.(variable2 = paste0(variable, 1:.N), value), 
        by = .(ID, date, variable)], 
       ID + date ~ variable2, value.var = "value") 

setcolorder(newDT, c(1:2, c(6, 12, 9, 15, 3), c(6, 12, 9, 15, 3)+1, c(6, 12, 9, 15, 3)+2)) 

결과 :

 ID  Date     BeginTime1     EndTime1 department1 room1 Bed1 
1 2156864 2016-03-02 2016-03-02 09:40:00.0000000 2016-03-02 15:20:00.0000000  L14B 102 3 
2 2161034 2016-06-06 2016-06-06 09:00:00.0000000 2016-06-06 10:27:00.0000000  B51A 109 2 
3 2161034 2016-06-07 2016-06-07 00:00:00.0000000 2016-06-07 11:02:00.0000000  B51A 109 2 
4 2176442 2016-02-04 2016-02-04 07:15:00.0000000 2016-02-04 13:47:00.0000000  L14B 101 4 
5 2176754 2016-03-15 2016-03-15 07:16:00.0000000 2016-03-15 14:56:00.0000000  B61A 109 3 
6 2176754 2016-03-16 2016-03-16 08:10:00.0000000 2016-03-17 00:00:00.0000000  B61A 109 3 
7 2176754 2016-03-17 2016-03-17 00:00:00.0000000 2016-03-17 11:18:00.0000000  B61A 109 3 
8 2184060 2016-03-10 2016-03-10 20:25:00.0000000 2016-03-11 00:00:00.0000000  B61A 105 2 
9 2184060 2016-03-11 2016-03-11 00:00:00.0000000 2016-03-12 00:00:00.0000000  B61A 105 2 
10 2184060 2016-03-12 2016-03-12 00:00:00.0000000 2016-03-12 14:00:00.0000000  B61A 105 2 
        BeginTime2     EndTime2 department2 room2 Bed2 
1       <NA>      <NA>  <NA> <NA> <NA> 
2 2016-06-06 12:47:00.0000000 2016-06-07 00:00:00.0000000  B51A 109 2 
3       <NA>      <NA>  <NA> <NA> <NA> 
4       <NA>      <NA>  <NA> <NA> <NA> 
5 2016-03-15 14:56:00.0000000 2016-03-16 08:10:00.0000000  B61A 109 2 
6       <NA>      <NA>  <NA> <NA> <NA> 
7       <NA>      <NA>  <NA> <NA> <NA> 
8 2016-03-10 20:01:00.0000000 2016-03-10 20:25:00.0000000  B61A 105 1 
9       <NA>      <NA>  <NA> <NA> <NA> 
10      <NA>      <NA>  <NA> <NA> <NA> 
        BeginTime3     EndTime3 department3 room3 Bed3 
1       <NA>      <NA>  <NA> <NA> <NA> 
2 2016-06-06 10:27:00.0000000 2016-06-06 12:47:00.0000000  B51A 103 3 
3       <NA>      <NA>  <NA> <NA> <NA> 
4       <NA>      <NA>  <NA> <NA> <NA> 
5       <NA>      <NA>  <NA> <NA> <NA> 
6       <NA>      <NA>  <NA> <NA> <NA> 
7       <NA>      <NA>  <NA> <NA> <NA> 
8       <NA>      <NA>  <NA> <NA> <NA> 
9       <NA>      <NA>  <NA> <NA> <NA> 
10      <NA>      <NA>  <NA> <NA> <NA> 

참고 : 나는 아직도 열을 재 배열 할 수있는 더 좋은 방법을 생각하기 위해 노력하고있어

. 이것은 제가 지금 얻을 수있는 최선입니다.

+0

@FtD 당신이 내 대답을 받아들이지 않았 음을 알았습니다. 잘못된 것이 있습니까? – useR

+0

아직 감사 드려요. 많은 행에는 여러 날짜의 데이터가 포함되어 있습니다 (예제에서 제공하지 않음). 이 경우 BeginTime과 EndTime 사이의 날짜가 출력으로 끝나지 않습니다. 그래서 나의 목표는 환자 당 입원 당일에 해당 위치가있는 행을 만드는 것입니다. 이 작업을 수행하는 쉬운 방법이 있습니까? 문제가 발생하는 내 질문에 다른 예제를 게시했습니다. – FtD

+0

@FtD 이해가 안됩니다. 무슨 뜻입니까? 많은 행에 여러 데이터의 데이터가 포함되어 있습니까? 내 솔루션은 방금 제공 한 새로운 예제에서 작동합니다. 어떻게 작동하지 않는지 설명해 주시겠습니까? – useR

관련 문제