17

我正在为我 11 年的临床实践处理大量账单记录数据集。相当多的行缺少转诊医生。但是,使用一些规则我可以​​很容易地填写它们,但不知道如何在 R 下的 data.table 中实现它。我知道有诸如na.locfzoo 包和 data.table 包中的自滚动连接之类的东西。我看到的例子太简单了,对我没有帮助。

这是一些用于指导您的虚构数据(作为 dput ASCII 文本表示)

    structure(list(patient.first.name = structure(c(1L, 1L, 1L, 1L, 
1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L), .Label = c("John", "Kathy", 
"Timothy"), class = "factor"), patient.last.name = structure(c(3L, 
3L, 3L, 3L, 3L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L), .Label = c("Jones", 
"Martinez", "Squeal"), class = "factor"), medical.record.nr = c(4563455, 
4563455, 4563455, 4563455, 4563455, 2663775, 2663775, 2663775, 
2663775, 2663775, 3330956, 3330956, 3330956, 3330956), date.of.service = c(39087, 
39112, 39112, 39130, 39228, 39234, 39244, 39244, 39262, 39360, 
39184, 39194, 39198, 39216), procedure.code = c(44750, 38995, 
40125, 44720, 44729, 44750, 38995, 40125, 44720, 44729, 44750, 
44729, 44729, 44729), diagnosis.code.1 = c(456.87, 456.87, 456.87, 
456.87, 456.87, 521.37, 521.37, 521.37, 521.37, 356.36, 456.87, 
456.87, 456.87, 456.87), diagnosis.code.2 = c(413, 413, 413, 
413, 413, 532.23, NA, NA, NA, NA, NA, NA, NA, NA), referring.doctor.first = structure(c(1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, NA, NA, NA, 1L, 1L, NA), .Label = c("Abe", 
"Mark"), class = "factor"), referring.doctor.last = structure(c(1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, NA, NA, NA, 1L, 1L, NA), .Label = c("Newstead", 
"Wydell"), class = "factor"), referring.docotor.zip = c(15209, 
15209, 15209, 15209, 15209, 15222, 15222, 15222, NA, NA, NA, 
15209, 15209, NA), some.other.stuff = structure(c(1L, 1L, 1L, 
NA, 3L, NA, NA, 4L, NA, 6L, NA, 2L, 5L, NA), .Label = c("alkjkdkdio", 
"cheerios", "ddddd", "dddddd", "dogs", "lkjljkkkkk"), class = "factor")), .Names = c("patient.first.name", 
"patient.last.name", "medical.record.nr", "date.of.service", 
"procedure.code", "diagnosis.code.1", "diagnosis.code.2", "referring.doctor.first", 
"referring.doctor.last", "referring.docotor.zip", "some.other.stuff"
), row.names = c(NA, 14L), class = "data.frame")

显而易见的解决方案是在 refer.doctor.last 和 refer.doctor.first 上使用某种最后观察结转 (LOCF) 算法。但是,当它到达新患者时,它必须停止。换言之,LOCF 必须仅应用于由患者.first.name、患者.last.name、medical.record.nr 的组合标识的一位患者。还要注意一些患者在第一次就诊时是如何错过转诊医生的,这意味着一些观察结果必须倒退。使事情复杂化的是,一些患者更换初级保健医生,因此可能会在更早的时候有一位转诊医生,而在以后可能会有另一位转诊医生。因此,该算法需要了解具有缺失值的行的日期顺序。

在动物园里na.locf,我看不到一个简单的方法来对每个病人的 LOCF 进行分组。我见过的滚动连接示例在这里不起作用,因为我不能简单地取出缺少 refering.doctor 信息的行,因为我会丢失 date.of.service 和 procedure.code 等。我希望您能帮助我了解 R 如何填补我缺失的数据。

4

2 回答 2

26

一个更简洁的例子会更容易回答。例如,您包含了相当多的列,这些列似乎是多余的。它真的需要按名字和姓氏,还是我们可以使用患者编号?

由于您已经NA在数据中有 s,您希望填写,它实际上并不roll存在data.table。当您的数据没有NA但您有另一个时间序列(例如)连接到数据之间的位置,滚动连接更适用。(一个效率优势是您不必先创建NA,然后必须填写第二步。)或者,换句话说,在您的问题中,您只有一个数据集;你没有加入两个。

所以你确实需要na.locf@Joshua 建议的那样。不过,我不知道有一个函数会NA向前填充,然后将第一个值向后填充。

data.tablena.locf按组使用它只是:

require(data.table)
require(zoo)
DT[,doctor:=na.locf(doctor),by=patient]

具有快速聚合和引用更新的效率优势。您必须在其上编写一个新的小函数na.locf才能将第一个非NA向后滚动。

确保数据首先按患者排序,然后按日期排序。那么以上将应对医生随时间的变化,因为by保持每组内的行顺序。

希望能给你一些提示。

于 2012-09-26T22:19:15.243 回答
22

@MatthewDowle 为我们提供了一个很好的起点,在这里我们将得出结论。

简而言之,使用zoona.locf. 该问题不适用于滚动连接。

setDT(bill)
bill[,referring.doctor.last:=na.locf(referring.doctor.last,na.rm=FALSE),
     by=list(patient.last.name, patient.first.name, medical.record.nr)]
bill[,referring.doctor.last:=na.locf(referring.doctor.last,na.rm=FALSE,fromLast=TRUE),
     by=list(patient.last.name, patient.first.name, medical.record.nr)]

然后做类似的事情referring.doctor.first

几点建议:

  1. by声明确保最后的观察结果仅限于同一患者,以便携带不会“流血”到列表中的下一个患者。

  2. 必须使用na.rm=FALSE论据。如果不这样做,那么在第一次就诊时缺少转诊医生信息的患者将被NA删除,并且新值的向量(现有 + 结转)将比行数少一个元素。缩短的向量被回收,所有内容都向上移动,最后一行在回收时获取向量的第一个元素。换句话说,大乱。最糟糕的是,您有时只会看到它。

  3. 用于fromLast=TRUE再次穿过该列。这会填充任何数据之前的 NA。动物园使用下一个后向观察(NOCB)代替最后一次观察结转(LOCF)。幸福——您现在已经以适合大多数情况的方式填写了缺失的数据。

  4. 您可以每行传递多个:=,例如DT[,`:=`(new=1L,new2=2L,...)]

于 2012-09-27T23:34:22.417 回答