我正在为11年以上的临床实践工作提供计费记录的大量数据集。相当一部分行缺少转诊医生。但是,使用一些规则我可以很容易地填充它们但不知道如何在R中的data.table中实现它。我知道在动物园包中有一些诸如na.locf
之类的东西和在自动滚动连接中data.table包。我看到的例子过于简单,并没有帮助我。
这里有一些虚构的数据来定位你(作为一个输入的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必须仅应用于由patient.first.name,patient.last.name,medical.record.nr的组合识别的一名患者。还要注意一些患者在第一次就诊时是否缺少转诊医生,这意味着必须进行一些观察向后。更复杂的是,一些患者会改变初级保健医生,因此可能会有一位早期转诊医生和另一位稍后转诊医生。因此,算法需要知道具有缺失值的行的日期顺序。
在动物园na.locf
中,我看不到为每位患者分组LOCF的简便方法。我看到的滚动连接示例在这里不起作用因为我不能简单地删除缺少refer.doctor信息的行,因为我将松开date.of.service和procedure.code等。我很乐意帮助您了解R如何填写我缺失的数据。
答案 0 :(得分:20)
简而言之,使用 zoo 的na.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
一些指示:
by
声明确保结转的最后一次观察仅限于同一患者,以便携带不会“流血”到列表中的下一位患者身上。
必须使用na.rm=FALSE
参数。如果没有,那么在第一次就诊时缺少推荐医生信息的患者将删除NA
,并且新值(现有+结转)的向量将是一个元素,不包括行。缩短的向量被循环使用,一切都向上移动,最后一行获得向量的第一个元素,因为它被循环使用。换句话说,一团糟。最糟糕的是,你有时只能看到它。
使用fromLast=TRUE
再次浏览该列。这填补了任何数据之前的NA。而不是最后一次观察结果(LOCF)动物园使用下一个观察结果(NOCB)。幸福 - 您现在已经以大多数情况下正确的方式填写了缺失的数据。
您可以每行传递多个:=
,例如DT[,`:=`(new=1L,new2=2L,...)]
答案 1 :(得分:19)
更简洁的例子会更容易回答。例如,您已经包含了很多看似冗余的列。它真的需要名字和姓氏,还是我们可以使用患者号码?
由于数据中已有NA
个,您希望填写,roll
中的data.table
确实不是NA
。当您的数据没有NA
但是您有另一个时间序列(例如)连接到之间数据时,滚动连接更适合。 (一个效率优势是你首先不创建na.locf
,然后你必须填写第二步。)或者换句话说,在你的问题中你只是有一个数据集;你没有加入两个。
所以你确实需要NA
@Joshua建议。我不知道有一个函数可以向前填充data.table
向前然后第一个值。
在na.locf
中,要按群组使用require(data.table)
require(zoo)
DT[,doctor:=na.locf(doctor),by=patient]
,只需:
na.locf
具有快速聚合和参考更新的效率优势。您必须在NA
之上编写一个新的小函数,以向后滚动第一个非by
。
确保首先按患者和日期对数据进行排序。然后上面将解决医生随时间的变化,因为{{1}}维持每组内行的顺序。
希望能给你一些提示。