Как определить, отличается ли значение от предыдущей строки, и повторить эту информацию в следующей строке (например, в цикле)?

#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 и перейдите к cumsum

2. Спасибо вам за вашу помощь @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