如何在R中对多列非数值分类数据使用pivot_longer
解决方案
你的问题核心是要将**成对的列(xN_date/xN_class)**转换为长格式的行,同时保留对应关系并移除全NA的行。以下是针对大规模数据(x0到x400)的高效实现:
正确代码
library(tidyverse) test <- df %>% pivot_longer( cols = matches("^x\\d+_(date|class)"), # 匹配所有xN_date/xN_class格式的列 names_to = c("group", ".value"), # group存分组标识,.value将date/class转为列 names_pattern = "^x(\\d+)_(date|class)", # 捕获分组数字和属性类型 values_drop_na = FALSE # 先保留NA,后续统一过滤 ) %>% filter(!is.na(date) | !is.na(class)) %>% # 移除date和class全为NA的无效行 select(-group) # 不需要分组标识的话可以删除该列
代码说明
- 列匹配:
matches("^x\\d+_(date|class)")精准定位所有x+数字+_date/_class格式的列,完美适配x0到x400的大规模数据。 - 命名规则:
group:存储每个成对列的分组标识(比如x0、x1);.value:pivot_longer的特殊参数,会将捕获到的date/class作为新列名,自动把对应值填充到列中,这是处理这类成对属性列转长表的关键。
- 正则捕获:
^x(\\d+)_(date|class)拆分列名,第一部分捕获x后面的数字,第二部分捕获属性类型(date或class)。 - 过滤无效行:用
filter移除date和class全为NA的行,避免无效数据干扰。
输出验证
运行代码后会得到你预期的结果:
name date class 1 sue 2020-1-20 biology 2 sue 2021-4-18 english 3 joe 2020-2-20 physics 4 tom 2020-3-20 chemistry 5 tom 2021-6-18 drama
原代码问题说明
你之前的代码错误地将names_to设为c("date", "class"),这会把分组数字存入date列、属性类型存入class列,完全颠倒了数据对应关系。使用.value参数才是处理这类成对属性列转长表的正确逻辑。
内容的提问来源于stack exchange,提问作者Bradley Allf
相关产品推荐
相关产品推荐

