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 每个 id
的 max
心率并折叠到一个记录,但是 我不知道该怎么做是有条件地将字符变量折叠为每组一条记录,因为只有一个唯一的非 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_each
和 distinct
.
来规避此问题
这是一个例子:
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 的方法可能更有效。
假设我有以下 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 每个 id
的 max
心率并折叠到一个记录,但是 我不知道该怎么做是有条件地将字符变量折叠为每组一条记录,因为只有一个唯一的非 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_each
和 distinct
.
这是一个例子:
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 的方法可能更有效。