R,dplyr:如果每组只有一个唯一的非 NA 元素,则按组折叠字符变量元素

R, dplyr: Collapse character variable elements by group if there is only one unique non-NA element per group

假设我有以下 data.frame df 患者家乡和一项任意临床指标,心率:

id          <- c(rep(1:3, each = 2), rep(4, 3))
pt_hometown <- c("Atlanta", NA, 
                 NA, "San Diego", 
                 NA, NA, 
                 "San Francisco", "Seattle", NA)
pt_heartrate <- c(NA, 82,
                  NA, NA,
                  76, 76,
                  90, 93, NA)

df <- data.frame(id = id, 
                 pt_hometown = pt_hometown,
                 pt_heartrate = pt_heartrate,
                 stringsAsFactors = FALSE)
df

这给出了

id   pt_hometown pt_heartrate
 1       Atlanta           NA
 1          <NA>           82
 2          <NA>           NA
 2     San Diego           NA
 3          <NA>           76
 3          <NA>           76
 4 San Francisco           90
 4       Seattle           93
 4          <NA>           NA

summarise_each 可以将一个或多个函数应用于分组数据框,以将记录折叠为每组一个。最简单的情况可能是 select 从 df 内的所有变量中提取第一个非 NA 值,并将它们折叠成每组一个。

  df1 <- df %>%  
    group_by(id) %>%
    summarise_each(funs(first(.[!is.na(.)]))

df1

id   pt_hometown pt_heartrate
 1       Atlanta           82
 2     San Diego           NA
 3            NA           76
 4 San Francisco           90

当然,对于实际应用来说,可能希望崩溃更具体一点。我知道如何按类型对 df 的变量进行分组,例如 select 每个 idmax 心率并折叠到一个记录,但是 我不知道该怎么做是有条件地将字符变量折叠为每组一条记录,因为只有一个唯一的非 NA 值

更具体地说,考虑编号为 id 4 的患者。他们有两个唯一值 pt_hometown、"San Francisco" 和 "Seattle"。显然两者都不可能是正确的。因此,我想折叠每个只有一个非 NA 值的组的记录,但保留存在多个非 NA 元素的行,然后将其引起我们组的注意决定如何纠正原始数据集中的错误。

所以我希望 df1 看起来像这样:

id   pt_hometown pt_heartrate
 1       Atlanta           82
 2     San Diego           NA
 3          <NA>           76
 4 San Francisco           90
 4       Seattle           93

这是我试过的:

df1 <- df %>%  
  group_by(id) %>%
  summarise_each_(funs(first(.[!is.na(.)])), df[length(unique(.[!is.na(.)])) == 1])

我不太清楚你对某些极端情况的要求,但这适用于 OP:

library(data.table)
dt = as.data.table(df) # or convert in place using setDT

unique(dt, by = c('id', 'pt_hometown'))[, lapply(.SD, na.omit), by = id]
#   id   pt_hometown pt_heartrate
#1:  1       Atlanta           82
#2:  2     San Diego           NA
#3:  3            NA           76
#4:  4 San Francisco           90
#5:  4       Seattle           93

如上所述,目前无法使用 dplyr::summarise_each 返回可变行数。

如果您想继续使用 dplyr,可以使用 mutate_eachdistinct.

来规避此问题

这是一个例子:

f <- function(.) if(length(unique(.[!is.na(.)])) > 1L) . else first(.[!is.na(.)]) 

df %>% 
  group_by(id) %>%
  mutate_each(funs(f)) %>%
  ungroup() %>%
  distinct() %>% 
  filter(rowSums(is.na(.)) < 2L)     # assuming you don't have NAs in the ID column

#Source: local data frame [5 x 3]
#
#  id   pt_hometown pt_heartrate
#1  1       Atlanta           82
#2  2     San Diego           NA
#3  3            NA           76
#4  4 San Francisco           90
#5  4       Seattle           93

但是,我对您之前问题的回答中的 data.table 方法或 eddi 的方法可能更有效。