R语言中按条件实现列转行:多Grade列合并与State映射处理需求问询
解决方案:宽格式转长格式并聚合匹配State列
这个需求其实是典型的宽格式转长格式并按值聚合的场景,coalesce确实不适用——它的作用是横向取多列的第一个非NA值,而不是纵向拆分多行来保留所有不同的Grade值。我们可以用tidyverse工具链来实现你的预期结果,具体步骤如下:
1. 加载依赖包并准备原始数据
首先确保你已经安装并加载了tidyverse,它包含了我们需要的pivot_longer和分组聚合函数:
library(tidyverse) # 原始数据集 df <- data.frame( id = c(1,2,3), role = c("A","B","C"), grade.1 = c(3,4,5), state.1 = c(1,NA,1), grade.2 = c(4,4,5), state.2 = c(1,1,NA), grade.3 = c(3,4,5), state.3 = c(1,1,NA) )
2. 将宽格式数据转为长格式
用pivot_longer把成对的grade.n和state.n列整理成纵向的结构,同时保留每一列的后缀数字(用来关联对应的state):
df_long <- df %>% pivot_longer( cols = starts_with(c("grade.", "state.")), # 选择所有grade和state开头的列 names_to = c(".value", "number"), # 把列名拆成两部分:.value对应grade/state,number对应后缀数字 names_pattern = "(grade|state)\\.(\\d)" # 正则匹配列名的结构 )
这一步会得到如下长格式数据:
# A tibble: 9 × 5 id role number grade state <dbl> <chr> <chr> <dbl> <dbl> 1 1 A 1 3 1 2 1 A 2 4 1 3 1 A 3 3 1 4 2 B 1 4 NA 5 2 B 2 4 1 6 2 B 3 4 1 7 3 C 1 5 1 8 3 C 2 5 NA 9 3 C 3 5 NA
3. 按id/role/Grade分组,匹配对应State列
接下来按id、role和grade分组,把每个分组中对应number的state值映射回原来的state.1/state.2/state.3列,没有匹配的则设为NA:
df.2 <- df_long %>% group_by(id, role, grade) %>% summarise( state.1 = first(state[number == "1"]), # 提取number=1对应的state值 state.2 = first(state[number == "2"]), # 提取number=2对应的state值 state.3 = first(state[number == "3"]), # 提取number=3对应的state值 .groups = "drop" # 取消分组 ) %>% rename(Grade = grade) # 把grade列重命名为你需要的Grade
最终结果
运行上述代码后,你会得到完全符合预期的数据集:
# A tibble: 4 × 6 id role Grade state.1 state.2 state.3 <dbl> <chr> <dbl> <dbl> <dbl> <dbl> 1 1 A 3 1 NA 1 2 1 A 4 NA 1 NA 3 2 B 4 NA 1 1 4 3 C 5 1 NA NA
关键说明
pivot_longer是处理宽转长场景的核心工具,通过正则匹配可以精准关联成对的列(比如grade.1和state.1)。- 分组聚合时,
first(state[number == "n"])会自动处理缺失情况:如果分组中没有对应number的条目,就返回NA,正好满足你的需求。
内容的提问来源于stack exchange,提问作者amisos55
相关产品推荐
相关产品推荐

