我正在尝试进行分析,为此我需要使数据的所有列都具有值。
我有很多病人的清单。在3种可能的情况下看病人: 紧急情况,门诊咨询和住院。
每个患者可以一次或多次去这些服务。
我们拥有的数据是:
问题在于患者来到急诊室,只有在该日期之前填写急诊诊断,外部咨询和住院将显示“ NA”。就像您来门诊就诊一样,您在该日期的急诊室和住院期间(如果您要去门诊就诊)会得到不适用。
pacient <- c(10,10,10,10,10,11,11,12,12,12); pacient
date <- as.Date(c("01/01/2018","02/01/2018", "04/04/2018", "10/05/2018", "05/09/2018", "02/01/2018", "06/08/2018", "01/01/2018", "03/01/2018", "06/08/2018"), format = "%d/%m/%Y"); date
set <- c("URG", "CEX", "CEX", "URG", "HOSP", "CEX", "URG", "CEX", "CEX", "URG")
dx_URG <- c("A", NA, NA, "B", NA, NA, "A", NA, NA, "B")
dx_CEX <- c(NA, "B", "C", NA, NA, "A", NA, "C", "B", NA)
dx_HOSP <- c(NA, NA, NA, NA, "A", NA, NA, NA,NA,NA)
DF <- data.frame(pacient, date, set, dx_URG, dx_CEX, dx_HOSP)); DF
我的数据:
pacient date set dx_URG dx_CEX dx_HOSP
1 10 01/01/2018 URG A <NA> <NA>
2 10 02/01/2018 CEX <NA> B <NA>
3 10 04/04/2018 CEX <NA> C <NA>
4 10 10/05/2018 URG B <NA> <NA>
5 10 05/09/2018 HOSP <NA> <NA> A
6 11 02/01/2018 CEX <NA> A <NA>
7 11 06/08/2018 URG A <NA> <NA>
8 12 01/01/2018 CEX <NA> C <NA>
9 12 03/01/2018 CEX <NA> B <NA>
10 12 06/08/2018 URG B <NA> <NA>
A,B,B,B,B
第一个值保持不变,第二个是NA变为B(自2018年10月5日以来访问URG给出诊断B),因此... 为了在10位患者的CEX中进行诊断,我在NA中填入了诊断C,并在HOSP中填入了诊断A。 我部分是通过以下代码实现的:
dx_remp <- lapply(DF, function(x){
setDT(DF)[, dx_URG:= na.aggregate(dx_URG, FUN=function(x){ tail(x[!is.na(x)],1)}), by = pacient]
setDT(DF)[, dx_CEX:= na.aggregate(dx_CEX, FUN=function(x){ tail(x[!is.na(x)],1)}), by = pacient]
setDT(DF)[, dx_HOSP:= na.aggregate(dx_HOSP, FUN=function(x){ tail(x[!is.na(x)],1)}), by = pacient]
return(num_vist)})
问题是当患者没有诊断要“填写”时此代码不起作用:例如,由于患者11和12都没有任何值,我在填写dx_HOSP时出错。 >
与此有关的第二件事是,如果患者没有值来填充我们要替换NA的列,请在另一个列中查找它: 优先级应为CEX-> HOSP-> URG
总而言之,我必须先填写NA,然后在其中查找列,如果没有值,则先搜索dx_CEX,然后搜索dx_HOS,然后搜索dx_URG。
所需结果:
pacient date set dx_URG dx_CEX dx_HOSP
1 10 01/01/2018 URG A C A
2 10 02/01/2018 CEX B B A
3 10 04/04/2018 CEX B C A
4 10 10/05/2018 URG B C A
5 10 05/09/2018 HOSP B C A
6 11 02/01/2018 CEX A A A
7 11 06/08/2018 URG A A A
8 12 01/01/2018 CEX B C B
9 12 03/01/2018 CEX B B B
10 12 06/08/2018 URG B B B
例如,dx_cex中的患者10的日期为1、4和5为空; dx_cex的NA必须填写该患者的最后一次Cex诊断,即C。在dx_hosp的患者12中,在任何引用中均无价值,因此有必要在cex,即B,并用B填充dx_hosp的所有NA。
谢谢
答案 0 :(得分:1)
基于新数据的适应。我们创建一个辅助函数,用最后一个非NA
值(如果有)填充NA
值,并使用它代替fill
:
fill_with_last = function(x) {
if (any(!is.na(x))) x[is.na(x)] = tail(na.omit(x), 1)
return(x)
}
DF %>%
# fix column classes (just in case)
mutate_if(is.factor, as.character) %>%
# ensure order is correct
arrange(pacient, date) %>%
# by pacient
group_by(pacient) %>%
# fill in the diagnosis variables with last observation
mutate_at(vars(starts_with("dx")), fill_with_last) %>%
# coalesce in priority order to fill in any blanks
mutate(dx_URG = coalesce(dx_URG, dx_CEX, dx_HOSP),
dx_CEX = coalesce(dx_CEX, dx_HOSP, dx_URG),
dx_HOSP = coalesce(dx_HOSP, dx_CEX, dx_URG))
# # A tibble: 10 x 6
# # Groups: pacient [3]
# pacient date set dx_URG dx_CEX dx_HOSP
# <dbl> <date> <chr> <chr> <chr> <chr>
# 1 10 2018-01-01 URG A C A
# 2 10 2018-01-02 CEX B B A
# 3 10 2018-04-04 CEX B C A
# 4 10 2018-05-10 URG B C A
# 5 10 2018-09-05 HOSP B C A
# 6 11 2018-01-02 CEX A A A
# 7 11 2018-08-06 URG A A A
# 8 12 2018-01-01 CEX B C C
# 9 12 2018-01-03 CEX B B B
# 10 12 2018-08-06 URG B B B
请注意,dx_Hosp
第8行存在差异。您期望的结果显示为“ B”,但是您描述的逻辑(由我和sindri共同实现)的结果为“ C”,因为dx_CEX
按优先级顺序排在dx_URG
之前。
这是我以为您想填写 next 诊断而不是 last 诊断的原始解决方案。它对tidyr
函数使用fill
(用先前的观察值填充缺失值),对dplyr
函数使用coalesce
(跨列获取第一个非缺失值):
library(tidyr)
library(dplyr)
DF %>%
# convert any factor columns to character for easy modification
mutate_if(is.factor, as.character) %>%
# make sure things are in the right order
arrange(pacient, date) %>%
# do subsequent operations "by pacient"
group_by(pacient) %>%
# fill in missing values "up" with the most recent observation,
# then fill "down" if there are other holes
fill(dx_URG, dx_CEX, dx_HOSP, .direction = "up") %>%
fill(dx_URG, dx_CEX, dx_HOSP, .direction = "down") %>%
# "coalesce" column in the order of preference
mutate(dx_URG = coalesce(dx_URG, dx_CEX, dx_HOSP),
dx_CEX = coalesce(dx_CEX, dx_HOSP, dx_URG),
dx_HOSP = coalesce(dx_HOSP, dx_CEX, dx_URG))
# # A tibble: 10 x 6
# # Groups: pacient [3]
# pacient date set dx_URG dx_CEX dx_HOSP
# <dbl> <date> <chr> <chr> <chr> <chr>
# 1 10 2018-01-01 URG A B A
# 2 10 2018-01-02 CEX B B A
# 3 10 2018-04-04 CEX B C A
# 4 10 2018-05-10 URG B C A
# 5 10 2018-09-05 HOSP B C A
# 6 11 2018-01-02 CEX A A A
# 7 11 2018-08-06 URG A A A
# 8 12 2008-01-01 CEX B C C
# 9 12 2018-01-03 CEX B B B
# 10 12 2018-08-06 URG B B B
几个数据说明。在您的代码中,第5行的年份为2008
,但是在表中,您的2018
则与其余所有年份一样。我将2008
更改为2018
以匹配表格。
执行cbind()
时,它将所有内容转换为matrix
,这将丢失您的列类。这是不好的。直接呼叫data.frame()
比使用as.data.frame(cbind())
更好。
# change this
DF <- as.data.frame(cbind(pacient, date, set, dx_URG, dx_CEX, dx_HOSP))
# to this
DF <- data.frame(pacient, date, set, dx_URG, dx_CEX, dx_HOSP)
答案 1 :(得分:0)
这是一个很有趣的问题,并提出了基于data.table
的{{1}}解决方案:
dplyr::case_when()