如何用tidyverse优雅批量提取数值列非0对应的分类向量?
问题描述
我有一个包含1个分类列和多个数值列的大型数据框,示例数据如下:
big_df <- data.frame(category = LETTERS[1:10] ,Q_COL1 = c(0,1,0,2,0,0,17,0,12,19) ,Q_COL2 = c(0,2,3,0,1,12,0,1,0,12) )
数据结构:
category Q_COL1 Q_COL2 1 A 0 0 2 B 1 2 3 C 0 3 4 D 2 0 5 E 0 1 6 F 0 12 7 G 17 0 8 H 0 1 9 I 12 0 10 J 19 12
需要为每个数值列生成对应的字符向量,保留数值大于0的category值,手动实现的示例代码如下:
col1_char <- big_df %>% select(category, Q_COL1) %>% filter(Q_COL1 > 0) %>% select(category) %>% deframe() col2_char <- big_df %>% select(category, Q_COL2) %>% filter(Q_COL2 > 0) %>% select(category) %>% deframe()
输出结果:
> col1_char [1] "B" "D" "G" "I" "J" > col2_char [1] "B" "C" "E" "F" "H" "J"
希望用更简洁的tidyverse方法批量处理,最终可输出填充NA的DataFrame或列表。
解决方案
方法1:生成列表(推荐,保留原始向量长度)
通过宽转长、过滤、分组嵌套的方式批量生成目标向量,最终存储为列表:
library(tidyverse) result_list <- big_df %>% pivot_longer(cols = starts_with("Q_COL"), names_to = "col_name", values_to = "value") %>% filter(value > 0) %>% group_by(col_name) %>% nest() %>% mutate(data = map(data, ~ deframe(.x))) %>% deframe()
查看结果:
> result_list$Q_COL1 [1] "B" "D" "G" "I" "J" > result_list$Q_COL2 [1] "B" "C" "E" "F" "H" "J"
方法2:生成带NA填充的DataFrame
先转长表过滤有效数据,为每个分组添加行号后转回宽表,自动用NA填充长度不足的位置:
result_df <- big_df %>% pivot_longer(cols = starts_with("Q_COL"), names_to = "col_name", values_to = "value") %>% filter(value > 0) %>% group_by(col_name) %>% mutate(row_id = row_number()) %>% pivot_wider(names_from = col_name, values_from = category) %>% select(-row_id)
输出结果:
> result_df # A tibble: 6 × 2 Q_COL1 Q_COL2 <chr> <chr> 1 B B 2 D C 3 G E 4 I F 5 J H 6 NA J
内容的提问来源于stack exchange,提问作者Wera
相关产品推荐
相关产品推荐

