2017-02-01 2 views
4

У меня есть два набора данных:Поиск ближайшего времени соответствия для каждого пациента

Первый набор:

patient<-c("A","A","B","B","C","C","C","C") 
arrival<-c("11:00","11:00","13:00","13:00","14:00","14:00","14:00","14:00") 
lastRow<-c("","Yes","","Yes","","","","Yes") 

data1<-data.frame(patient,arrival,lastRow) 

Другой набор данных:

patient<-c("A","A","A","A","B","B","B","C","C","C") 
availableSlot<-c("11:15","11:35","11:45","11:55","12:55","13:55","14:00","14:00","14:10","17:00") 

data2<-data.frame(patient, availableSlot) 

Я хочу создать добавить столбец к первому набору данных, который для каждой последней строки каждого пациента показывает доступный слот, который равен , ближайшему к времени прибытия:

Результаты будут:

patient arrival lastRow availableSlot 
     A 11:00   
     A 11:00  Yes  11:15 
     B 13:00   
     B 13:00  Yes  12:55 
     C 14:00   
     C 14:00   
     C 14:00   
     C 14:00  Yes  14:00 

бы признателен, если кто-нибудь может сказать мне, как я могу осуществить это в R.

+0

вам, вероятно, нужно преобразовать столбцы с часами до даты класса первых – Cath

+0

так этого? 'merge (data1, data2 [!duplicated (data2 $ patient),], by = 'patient') ', если ваш' data2' упорядочен по 'прибытию' – Sotos

+2

@Sotos Нет, это просто повезло. OP сказал «ближайший», который совпадает с первым здесь. – Frank

ответ

8

Я хотел бы использовать data.table, первый очистки путем преобразования в ITime и игнорирование избыточные строки:

library(data.table) 
setDT(data1)[, arrival := as.ITime(as.character(arrival))] 
setDT(data2)[, availableSlot := as.ITime(as.character(availableSlot))] 
DT1 = unique(data1, by="patient", fromLast=TRUE) 

Тогда вы можете сделать "прокатка присоединиться":

res = data2[DT1, on=.(patient, availableSlot = arrival), roll="nearest", 
    .(patient, availableSlot = x.availableSlot)] 

# patient availableSlot 
# 1:  A  11:15:00 
# 2:  B  12:55:00 
# 3:  C  14:00:00 

Как это работает

Синтаксис: x[i, on=, roll=, j].

  • on= - это столбцы слияния.
  • Это соединение: для каждой строки i мы ищем совпадения в x.
  • С последний столбец в on= «свернут» до ближайшего совпадения.
  • В столбцах on= в исходных таблицах можно указать x.* и i.* префиксы.
  • Аргумент j должен содержать список столбцов, а .() - это псевдоним для list().

Заканчивать вводные материалы пакета 'в http://r-datatable.com/Getting-started и типе ?data.table для документации, имеющей отношение к прокатке присоединяется.


я хотел бы остановиться на res, но если вы действительно хотите его обратно в исходную таблицу ...

# a very nonstandard step: 
data1[lastRow == "Yes", availableSlot := res$availableSlot ] 

# patient arrival lastRow availableSlot 
# 1:  A 11:00:00     <NA> 
# 2:  A 11:00:00  Yes  11:15:00 
# 3:  B 13:00:00     <NA> 
# 4:  B 13:00:00  Yes  12:55:00 
# 5:  C 14:00:00     <NA> 
# 6:  C 14:00:00     <NA> 
# 7:  C 14:00:00     <NA> 
# 8:  C 14:00:00  Yes  14:00:00 

Теперь data1 имеет availableSlot в новой колонке, подобный тому, когда Вы делаете data1$col <- val ,

+3

блестящее объяснение +1! –

+1

Отличное объяснение, как всегда – akrun

+0

Большое спасибо за вашу помощь. Могу ли я спросить, что x в x.availableSlot? –

1

Вот решение (на основе joel.wilson's answer на мой вопрос), который будет работать с базой R

#Convert dates to POSIXct format 
data1$arrival = as.POSIXct(data1$arrival, format = "%H:%M") 
data2$availableSlot = as.POSIXct(data2$availableSlot, format = "%H:%M") 

#Lookup times from data2$availableSlot closest to data1$arrival 
data1$availableSlot = sapply(data1$arrival, function(x) 
        data2$availableSlot[which.min(abs(x - data2$availableSlot))]) 

#Keep just hour and minutes 
data1$availableSlot = strftime(as.POSIXct(data1$availableSlot, 
           origin = "1970-01-01"), format = "%H:%M") 
data1$arrival = strftime(as.POSIXct(data1$arrival), format = "%H:%M") 

#Remove times when lastrow is empty 
data1$availableSlot[which(data1$lastRow != "Yes")] = "" 
Смежные вопросы