样本数据
df <- data.frame( id = 1:10,
group = c(1,1,1,1,1,2,2,2,2,2),
p1 = c("A", NA, "A", "A", "B", NA, NA, NA, NA, "C"),
p2 = c("F", NA, "G", "G", "A", "H", NA, NA, NA, NA),
stringsAsFactors = FALSE )
# id group p1 p2
# 1 1 1 A F
# 2 2 1 <NA> <NA>
# 3 3 1 A G
# 4 4 1 A G
# 5 5 1 B A
# 6 6 2 <NA> H
# 7 7 2 <NA> <NA>
# 8 8 2 <NA> <NA>
# 9 9 2 <NA> <NA>
# 10 10 2 C <NA>
我想按组总结df
,以便获得总计的列
NA
的唯一ID 所需的输出
data.frame( group = c(1,2),
total = c(5,5),
with_any_p = c(4,2),
with_any_p_is_A = c(4,0),
stringsAsFactors = FALSE)
# group total with_any_p with_any_p_is_A
# 1 1 5 4 4
# 2 2 5 2 0
到目前为止的代码
我知道我可以使用以下方法获得所需的输出
df %>% group_by( group ) %>%
summarise( total = n_distinct( id[] ),
with_any_p = n_distinct( id[ !is.na(p1) | ! is.na(p2) ] ),
with_any_p_is_A = n_distinct( id[ p1 == "A" | p2 == "A" ], na.rm = TRUE ) )
# # A tibble: 2 x 4
# group total with_any_p with_any_p_is_A
# <dbl> <int> <int> <int>
# 1 1 5 4 4
# 2 2 5 2 0
问题
但是由于我的生产数据包含很多“ p列”,所以我不想为p1-p100重新输入上述or语句
我可以使用filter_at
选择所需的行/子集:
p.cols <- paste0( "p", 1:2 )
#for with_any_p
df %>% filter_at( vars( p.cols ), any_vars( !is.na(.) ) )
#for with_any_p_is_A
df %>% filter_at( vars( p.cols ), any_vars( . == "A" ) )
但我现在确实知道如何总结这些选择。
能否以与我已有的代码相同的“样式”完成操作,以便一劳永逸地获得所需结果,而不必绑定/合并多个结果?
答案 0 :(得分:3)
这是使用初始的宽到长转换为任意数量的"p"
列的解决方案
df %>%
gather(key, val, -id, -group) %>%
group_by(group) %>%
summarise(
total = n_distinct(id),
with_any_p = n_distinct(id[!is.na(val)]),
with_any_p_is_A = n_distinct(id[val == "A"], na.rm = T))
## A tibble: 2 x 4
# group total with_any_p with_any_p_is_A
# <dbl> <int> <int> <int>
#1 1 5 4 4
#2 2 5 2 0
评论:我假设除id
和group
以外的所有列均为"p"
列。如果不是这种情况,则可能必须更改gather
语句以反映您更一般的列结构。