如何使用 R 中不同列的数据替换不正确的日期

How to replace incorrect dates by using data from a different column in R

我正在清理一个大型医疗数据集。有些手术日期当然是不可能的(入院日期前一个世纪!)。下面是一个例子 df:

doa = c("2010-08-01", "2010-08-07", "2008-09-01") # date of admission
doo_1 = c("2010-08-02", "1900-01-01", "2008-09-03") # date of first op
doo_2 = c("1800-01-01", "1900-01-01", "2008-09-03") # date of second op
df= data.frame (doa, doo_1, doo_2)

当第 2 列和第 3 列(在实际数据集中有 25 列)中的值小于 doa 时,我想将其替换为 doa+1(因为操作往往在入院后的第二天发生)。

With data.table :您首先创建一个患者编号变量 ptn

DT <- setDT(df)
setnames(DT,"doa","doo")
DT[,ptn := .I]

然后你融化你的数据

plouf <- melt(DT,measure.vars = patterns("^doo"))
plouf[,value:= as.Date(value)]
plouf[,.SD,by = ptn]
   ptn variable      value
1:   1      doo 2010-08-01
2:   1    doo_1 2010-08-02
3:   1    doo_2 1800-01-01
4:   2      doo 2010-08-07
5:   2    doo_1 1900-01-01
6:   2    doo_2 1900-01-01
7:   3      doo 2008-09-01
8:   3    doo_1 2008-09-03
9:   3    doo_2 2008-09-03

然后您计算每个操作和每个患者的输入日期之间的差异(“by = ptn”分组操作允许这样做,并且您知道因为命名,您的 doa 是每个组中的第一个)

plouf[,diff := value - value[1],by = ptn]

如果差值为负,则将日期设置为输入日期+1

plouf[diff <0,value := value[1]+1,by = ptn]

然后将数据重塑为初始形状

dcast(plouf, ptn ~variable )

   ptn        doo      doo_1      doo_2
1:   1 2010-08-01 2010-08-02 1800-01-02
2:   2 2010-08-07 1900-01-02 1900-01-02
3:   3 2008-09-01 2008-09-03 2008-09-03

不过我还是建议你用最后一个操作 +1 来代替这个奇怪的日期,而不是输入 patient。您可以按照以下步骤

plouf[diff <0,value := as.Date(NA),by = ptn] # create NA to use locf
library(zoo)
plouf[,value := na.locf(value), by = ptn] # use locf
plouf[diff<0, value := value +1] # add one day
dcast(plouf, ptn ~variable )

   ptn        doo      doo_1      doo_2
1:   1 2010-08-01 2010-08-02 2010-08-03
2:   2 2010-08-07 2010-08-08 2010-08-08
3:   3 2008-09-01 2008-09-03 2008-09-03

OP 已要求将不太可能的手术日期替换为 doa + 1(入院后的第二天)。

如果这个简单的规则将应用于所有 25 列,不需要将数据集从宽格式重塑为长格式并再次回到宽格式。

library(data.table)

# coerce date columns from factor or character to IDate
date_cols <- c("doa", "doo_1", "doo_2")
setDT(df)[, (date_cols) := lapply(.SD, as.IDate), .SDcols = date_cols][]
# replace dates if improbable
df[doo_1 < doa, doo_1 := doa + 1L][]
df[doo_2 < doa, doo_2 := doa + 1L][]
          doa      doo_1      doo_2
1: 2010-08-01 2010-08-02 2010-08-02
2: 2010-08-07 2010-08-08 2010-08-08
3: 2008-09-01 2008-09-03 2008-09-03

OP 提到生产数据集包含 25 列。这需要一个更灵活的解决方案,其中要处理的列名不是硬编码的,而是在向量中提供的:

op_cols <- c("doo_1", "doo_2")
for (x in op_cols) {
  df[get(x) < doa, (x) := doa + 1L]
}
df[]

请注意 data.table 通过引用更新,即不复制整个数据对象,只复制选定的元素。