如何对日期不匹配的日期-变量组合执行pivot_longer转换?
解决宽表转长表:配对列的处理问题
你之前的两次pivot_longer操作会把所有日期列和Equity列做笛卡尔积,产生大量无效的交叉组合,所以得不到预期结果。核心问题是你的数据中日期列与对应的Equity列是成对出现的(比如date1对应A Equity,date2对应B Equity),我们需要把每一对列作为整体处理,而非分开转换。
下面提供两种适合大规模数据(1000+列)的解决方案:
方案1:针对两两排列的配对列(通用场景)
如果你的数据列严格按照「日期列 + Equity列」的顺序两两分组(如示例数据),可以用purrr批量处理每一组列,再合并结果:
library(dplyr) library(purrr) library(stringr) # 将列名按两两一组拆分 column_pairs <- split(colnames(df), ceiling(seq_along(colnames(df)) / 2)) # 遍历每组列,提取并整理数据 desired_df <- map_dfr(column_pairs, function(pair) { df %>% select(all_of(pair)) %>% # 重命名为统一的date和value列 rename(date = pair[1], value = pair[2]) %>% # 从Equity列名中提取变量名(移除" Equity"后缀) mutate(var = str_remove(pair[2], " Equity")) %>% # 过滤空值行 filter(!is.na(date), !is.na(value)) })
这个方法不依赖列名的特殊规律,只要列是两两配对排列的就能用,非常适合你的大规模数据场景。
方案2:利用列名正则匹配(规律化列名场景)
如果你的日期列都是date开头加编号(如date1、date2),对应的Equity列是「变量名 + Equity」(如A Equity、B Equity),且编号与变量名顺序对应(date1对应A,date2对应B),可以用tidyr的正则匹配功能处理:
library(dplyr) library(tidyr) library(stringr) desired_df <- df %>% # 转换日期列为长格式,提取编号 pivot_longer( cols = starts_with("date"), names_to = "var_number", values_to = "date", names_transform = list(var_number = ~str_remove(.x, "date") %>% as.integer()) ) %>% # 转换Equity列为长格式,提取变量名 pivot_longer( cols = ends_with("Equity"), names_to = "var", values_to = "value", names_transform = list(var = ~str_remove(.x, " Equity")) ) %>% # 匹配编号与变量名的顺序(date1对应第1个字母A,以此类推) mutate(var_position = match(var, LETTERS)) %>% filter(var_number == var_position) %>% # 保留目标列并过滤空值 select(date, var, value) %>% filter(!is.na(date), !is.na(value))
验证结果
运行上述代码后,你会得到与预期完全一致的结果:
# # A tibble: 5 × 3 # date var value # <chr> <chr> <dbl> # 1 1/29/2016 A 35 # 2 2/29/2016 A 40 # 3 10/31/2017 B 67 # 4 11/30/2017 B 31 # 5 12/29/2017 B 56
内容的提问来源于stack exchange,提问作者Geet
相关产品推荐
相关产品推荐

