如何查找值是否与上一行不同并在下一行重复该信息(如循环)?

How to find if a value differs from the previous line and repeat that information in next line (like a loop)?

问题

标题具有误导性,因为它比那更复杂。我需要从 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)

如您所见,由于第 2 行的“2021-07-13”与第 1 行的“2021-07-10”不同,因此表明该患者住院人数增加的预期结果。

我的尝试

首先,我开始为新变量创建一个基值

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”重复到第三行,也就是和第二行一样的住院,所以不知道第四行的“3”怎么找,因为这是该患者的第三次住院。

解决方案

感谢 Ronak Shah !

data_set[, result := cumsum(date_entry != shift(date_exit, fill = FALSE)), patient_id]

首先,您必须准备数据集 - 您基本上只想比较下一个入口和上一个出口。第一次进入不会有之前的出口,所以可以删除第一次进入,最后一次出口不会有进入。


# ==== 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

接下来,计算exit和left之间的时间差(删除后我们要相减的值在彼此下方),并将其与零进行比较以获得真相table:

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)

最后,由于false被当成0,true被当成1,我们可以直接计算累加和。

vals <- cumsum(values)

基本上就这些了,您只需要拆分数据,因此它会 运行 对每一列(每个患者)进行拆分。这可以通过过滤具有特定 ID 的列并为每个患者创建一个临时 table(根据 patient_ID 获取您的集合的子集)

来完成

我不确定我是否理解你 - 我希望它能解决你的问题:)

如果前一行的 date_exit 与每个 patient_id 的当前 date_entry 不同,您可以增加计数。

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