2017-11-09 8 views
0

病院入院時の患者の位置を保持するデータフレームを使用しています。各行は、その人物(= ID)の一定期間(BeginTimからEndTimeまで)の新しい場所(=部門、部屋、ベッド)を表すように書式が設定されています。ここでデータフレームを期間ごとの行から1日に1行に変換する

は、初期データフレームのサンプルです:

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と2つのif文を結合しました。これまでの私の試みは、望みの結果に近いものを与えていないし、もっと簡単な方法でなければならないと思う。私はR、まだ学習に非常に新しいです

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 

:望ましい結果は次のようになります

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

第二の例:

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

実際、大きなデータフレームから2つの異なるサンプルを投稿しました。質問を編集して、IDがサンプルに一致するようにしました。 – FtD

+0

は、data.tables dcastで1つのライナーのように見えますが、データを自分自身でコピーするのは怠惰です。 "data < - data.frame(x = 1:10、y = 11)という形で再現可能な例を提供できますか? :20) "私はちょうどこれを確認するためにペーストをコピーできますか?あるいは、 "data

答えて

0

OPは、特定の場所で1日以上滞在していても、患者の日の位置を集計することを要求しています。

これは、最大でも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を持つソリューションです:

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

関連する問題