#r #difference
Вопрос:
Проблема
Название вводит в заблуждение, поскольку оно более сложное, чем это. Мне нужно найти разницу в значениях между 2 строками, но из 2 разных переменных, и мне также нужно повторить эту информацию для всех строк ниже.
У меня есть список пациентов, которые приходили и выходили из больницы, где я работаю. Иногда во время госпитализации их переводят из одного отделения в другое (например, из отделения неотложной помощи в отделение интенсивной терапии).
Я хочу знать, сколько времени они на самом деле уехали, а затем вернулись в больницу.
Чтобы найти это, мне просто нужно найти разницу во времени между днем входа и предыдущим днем выхода. Если оба равны, то это одно и то же пребывание. Если они отличаются, то это еще одно пребывание.
Это довольно сложно объяснить с моим уровнем английского языка, поэтому я приведу вам пример ниже.
Пример
Я работаю с data.table
, но вы можете использовать dplyr
, если хотите. Я должен быть в состоянии легко преобразовать его.*
# ==== Library ====
require(data.table)
# ==== Data set ====
## The patient id, the unit id, and the entry and exit date from individuals unit
patient_id <- c(rep(x = "0034280", 4), rep(x = "0002050", 2))
unit_id <- c(c("azr", "grt", "chd", "grt"), c("tgo", "grt"))
date_entry <- c(c("2021-07-10", "2021-07-13", "2021-07-14", "2021-07-30"),c("2021-07-29", "2021-07-30"))
date_exit <- c(c("2021-07-10", "2021-07-14", "2021-07-25", "2021-07-30"),c("2021-07-30", "2021-07-30"))
## The variable I want to get
expected_result <- c(c(1,2,2,3), c(1,1))
## Final result expected
data_set <- data.table(patient_id, unit_id, date_entry, date_exit, expected_result)
Как вы можете видеть, поскольку «2021-07-13» в строке 2 отличается от «2021-07-10» в строке 1, ожидаемый результат, указывающий на увеличение числа госпитализаций для этого пациента, увеличился.
Моя попытка
Во-первых, я начинаю создавать базовое значение для новой переменной
data_set <- data_set[
j = stay_number := 1
]
Затем, с помощью функции shift, я могу проверить разницу между двумя последовательными строками.
data_set <- data_set[
j = stay_number := data.table::fifelse(test = date_entry != data.table::shift(date_exit, type = "lag"),
yes = stay_number 1,
no = stay_number),
by = patient_id
][
j = stay_number := data.table::fifelse(test = base::is.na(stay_number),
yes = 1,
no = stay_number)
]
Но я не знаю, как повторить цифру «2» в третьей строке, которая является такой же госпитализацией, как и строка 2. Поэтому я не знаю, как найти «3» в четвертом ряду, так как это третья госпитализация для этого пациента.
Решение
Спасибо Ронаку Шаху !
data_set[, result := cumsum(date_entry != shift(date_exit, fill = FALSE)), patient_id]
Комментарии:
1. Хорошо, я полагаю, что понимаю, поэтому в основном вы просто хотите добавить некоторую фиктивную переменную для контейнера date_exit в начале(или удалить первую из контейнера date_start), а затем просто минус date_entry — date_exit. Вероятно, вам придется использовать какую-то функцию разницы дат(например
difftime
). Там вы сможете сравнить его с нулем, чтобы проверить, есть ли разница между оставшейся датой и датой ввода. Ты это имел в виду?
Ответ №1:
Во — первых, вы должны подготовить свой набор данных-вы в основном хотите только сравнить СЛЕДУЮЩУЮ запись с ПРЕДЫДУЩИМ выходом. Для первого входа не будет предыдущего выхода, поэтому первая запись может быть удалена, а для последнего выхода не будет записи.
# ==== Library ====
require(data.table)
# ==== Data set ====
## The patient id, the unit id, and the entry and exit date from individuals unit
patient_id <- c(rep(x = "0034280", 4), rep(x = "0002050", 2))
unit_id <- c(c("azr", "grt", "chd", "grt"), c("tgo", "grt"))
date_entry <- c(c("2021-07-10", "2021-07-13", "2021-07-14", "2021-07-30"),c("2021-07-29", "2021-07-30"))
date_exit <- c(c("2021-07-10", "2021-07-14", "2021-07-25", "2021-07-30"),c("2021-07-30", "2021-07-30"))
date_exitT <- date_exit[1:(length(date_entry)-1)] #remove last exit
date_entryT <- date_entry[2:length(date_exit)] #remove first entry
Затем просто вычислите разницу во времени между выходом и выходом(после удаления значения, которые мы должны вычесть, лежат друг под другом) и сравните ее с нулем, чтобы получить таблицу истинности:
output<-difftime(date_exitT, date_entryT, units="days")
values<-!(output==0) #negation because we actually want zeros to be falses and all others trues
values <- c(TRUE, values) #because we want to add 1 to the result(we always starting from 1 as I see from the result)
И, наконец, поскольку «ложь» трактуется как 0, а «истина» как 1, мы можем просто рассчитать совокупную сумму.
vals <- cumsum(values)
Это в основном все, вам просто нужно разделить свои данные, чтобы они выполнялись для каждого столбца(каждого пациента). Это можно сделать, отфильтровав столбцы с определенным идентификатором и создав временную таблицу для каждого пациента(взяв подмножество вашего набора на основе patient_ID).
Я не уверен, хорошо ли я вас понял — надеюсь, это решит вашу проблему 🙂
Комментарии:
1. Вы, вероятно, также могли бы повысить эффективность, не используя
difftime
функцию, просто сравните, если строки равны — если да, поставьте 0, если нет, поставьте 1 и перейдите к cumsum2. Спасибо вам за вашу помощь
@Lidbey
! Это то, к чему я стремился, и использованиеcumsum
было действительно умным. Как вы сказали, сравнение строк происходит быстрее. @ronak-shah нашел совершенно чистый способ сделать это.
Ответ №2:
Вы можете увеличить количество, если date_exit
предыдущая строка отличается от текущей date_entry
для каждой patient_id
.
library(data.table)
data_set[, result := cumsum(date_entry != shift(date_exit, fill = FALSE)), patient_id]
# patient_id unit_id date_entry date_exit expected_result result
#1: 0034280 azr 2021-07-10 2021-07-10 1 1
#2: 0034280 grt 2021-07-13 2021-07-14 2 2
#3: 0034280 chd 2021-07-14 2021-07-25 2 2
#4: 0034280 grt 2021-07-30 2021-07-30 3 3
#5: 0002050 tgo 2021-07-29 2021-07-30 1 1
#6: 0002050 grt 2021-07-30 2021-07-30 1 1