如何用tidyverse的pivot_longer将多列宽表转为指定长表结构
解决方案
假设你的宽格式数据包含阴性对照、阳性对照的开始/结束时间,以及实验组的开始/结束时间,以下是基于tidyverse的实现方法:
1. 示例数据
先定义一个最小可复现的示例数据集:
df <- structure(list( neg_control_start = c("2023-01-01 09:00", "2023-01-02 09:00"), neg_control_end = c("2023-01-01 10:00", "2023-01-02 10:00"), pos_control_start = c("2023-01-01 11:00", "2023-01-02 11:00"), pos_control_end = c("2023-01-01 12:00", "2023-01-02 12:00"), exp_start = c("2023-01-01 13:00", "2023-01-02 13:00"), exp_end = c("2023-01-01 14:00", "2023-01-02 14:00") ), class = "data.frame", row.names = c(NA, -2L))
2. 转换代码
使用tidyverse的pivot_longer和pivot_wider函数完成格式转换:
library(tidyverse) result <- df %>% # 将所有时间列转成长格式,拆分列名为分组类型和时间类型 pivot_longer( cols = everything(), names_to = c("group_type", "time_type"), names_pattern = "(.*)_(start|end)", values_to = "time" ) %>% # 将start/end转成独立列 pivot_wider( names_from = time_type, values_from = time ) %>% # 创建control二进制列:对照组标记为1,实验组标记为0 mutate( control = if_else(str_detect(group_type, "control"), 1, 0), # 可选:将时间字符串转换为时间格式 start_time = as.POSIXct(start), end_time = as.POSIXct(end) ) %>% # 保留目标列 select(control, start_time, end_time)
3. 输出结果
转换后的数据集结构如下:
# A tibble: 6 × 3 control start_time end_time <dbl> <dttm> <dttm> 1 1 2023-01-01 09:00:00 2023-01-01 10:00:00 2 1 2023-01-01 11:00:00 2023-01-01 12:00:00 3 0 2023-01-01 13:00:00 2023-01-01 14:00:00 4 1 2023-01-02 09:00:00 2023-01-02 10:00:00 5 1 2023-01-02 11:00:00 2023-01-02 12:00:00 6 0 2023-01-02 13:00:00 2023-01-02 14:00:00
代码说明
pivot_longer通过正则表达式names_pattern拆分列名,把neg_control_start拆分为group_type=neg_control和time_type=start;pivot_wider把分散的start/end时间值转成单独的列;mutate里的str_detect判断分组类型是否包含"control",以此生成二进制的control列;- 可选的时间格式转换确保
start_time和end_time为可操作的时间类型。
内容的提问来源于stack exchange,提问作者Eizy
相关产品推荐
相关产品推荐

