如何在R语言中生成新列并返回所有符合条件的列标题(行拆分)
实现将所有"Yes"列标题拆分为多行的R方法
原始数据
先还原你的原始DataFrame:
DF <- data.frame( ID = 1:7, Mon = c("Yes", "No", "No", "No", "Yes", "Yes", "No"), Tue = c("No", "No", "No", "Yes", "Yes", "Yes", "No"), Wed = c("No", "Yes", "No", "No", "No", "Yes", "Yes"), Thur = c("No", "No", "No", "Yes", "Yes", "Yes", "Yes"), Count_Y = c(1, 1, 0, 2, 3, 4, 2), stringsAsFactors = FALSE )
你原来用case_when的写法只能匹配第一个符合条件的列,没法把所有值为"Yes"的列标题都提取出来并拆分成多行,下面是两种可行的解决方案:
方法1:用tidyr::pivot_longer(推荐)
这是tidyverse生态里最简洁的实现方式,通过宽表转长表完成需求:
library(dplyr) library(tidyr) DF_result <- DF %>% # 将Mon到Thur的列转成长表,列名存到New_column,值存到临时列status pivot_longer( cols = Mon:Thur, names_to = "New_column", values_to = "status" ) %>% # 按ID分组,判断当前行是否存在Yes group_by(ID) %>% mutate(has_yes = any(status == "Yes")) %>% ungroup() %>% # 保留Yes的行,或者全No的行 filter(status == "Yes" | !has_yes) %>% # 全No的行把New_column设为OFF mutate(New_column = ifelse(!has_yes, "OFF", New_column)) %>% # 删除临时列,按ID排序 select(-status, -has_yes) %>% arrange(ID)
方法2:用rowwise+purrr::map逐行处理
如果习惯逐行逻辑处理,可以用这种方式:
library(dplyr) library(purrr) library(tidyr) DF_result <- DF %>% rowwise() %>% # 逐行判断:全No则返回"OFF"列表,否则返回所有Yes对应的列名列表 mutate( New_column = list( if (all(c(Mon, Tue, Wed, Thur) == "No")) { "OFF" } else { c("Mon", "Tue", "Wed", "Thur")[c(Mon, Tue, Wed, Thur) == "Yes"] } ) ) %>% # 将列表列拆分成多行 unnest(New_column) %>% ungroup() %>% arrange(ID)
运行任意一种方法后,都能得到你期望的输出:
# A tibble: 15 × 6 ID Mon Tue Wed Thur Count_Y New_column <int> <chr> <chr> <chr> <chr> <dbl> <chr> 1 1 Yes No No No 1 Mon 2 2 No No Yes No 1 Wed 3 3 No No No No 0 OFF 4 4 No Yes No Yes 2 Tue 5 4 No Yes No Yes 2 Thur 6 5 Yes Yes No Yes 3 Mon 7 5 Yes Yes No Yes 3 Tue 8 5 Yes Yes No Yes 3 Thur 9 6 Yes Yes Yes Yes 4 Mon 10 6 Yes Yes Yes Yes 4 Tue 11 6 Yes Yes Yes Yes 4 Wed 12 6 Yes Yes Yes Yes 4 Thur 13 7 No No Yes Yes 2 Wed 14 7 No No Yes Yes 2 Thur
内容的提问来源于stack exchange,提问作者user20835011
相关产品推荐
相关产品推荐

