如何在data.table中高效转换宽表为长格式并关联对应大小写变量?
问题描述
现有如下data.table:
foo bar a1 a2 a3 b1 b2 b3 b4 c1 c2 A_1 A_2 A_3 C_1 C_2 m 19 0 1 2 2 1 3 0 0 2 25 33 61 50 50 f 30 1 2 1 0 4 2 1 2 2 10 43 30 45 73 n 22 0 2 2 1 3 1 0 1 2 7 84 33 12 40
需要将其转换为长格式,每行对应一个小写字母开头的变量,同时携带匹配的大写字母开头变量,无匹配项时填充NA。期望结果片段如下:
foo bar lower lower_value upper upper_value m 19 a1 0 A_1 25 m 19 a2 1 A_2 33 ... f 30 b4 1 B_4 NA ... n 22 c2 2 C_2 40
补充的data.table定义代码:
library(data.table) dt <- data.table( foo = c("m", "f", "n"), bar = c(19, 30, 22), a1 = c(0, 1, 0), a2 = c(1, 2, 2), a3 = c(2, 1, 2), b1 = c(2, 0, 1), b2 = c(1, 4, 3), b3 = c(3, 2, 1), b4 = c(0, 1, 0), c1 = c(0, 2, 1), c2 = c(2, 2, 2), A_1 = c(25,10,7), A_2 = c(33,43,84), A_3 = c(61,30,33), C_1 = c(50,45,12), C_2 = c(50,73,40) )
最优实现方法
利用data.table原生的melt函数分三步处理,是适配data.table生态的高效方案:
- 拆分并重塑小写前缀列:提取所有小写字母开头的列,转成长格式,记录变量名
lower和对应值lower_value - 拆分并重塑大写前缀列:提取所有大写字母开头的列,转成长格式,同时生成匹配用的键(将
A_1这类格式转为a1) - 合并两个结果集:以
foo、bar和匹配键为关联条件合并,无匹配的大写变量自动填充NA
具体代码如下:
library(data.table) # 处理小写前缀列,转长格式 lower_melted <- melt(dt, id.vars = c("foo", "bar"), measure.vars = grep("^[a-z]", names(dt), value = TRUE), variable.name = "lower", value.name = "lower_value") # 处理大写前缀列,转长格式并生成匹配键 upper_melted <- melt(dt, id.vars = c("foo", "bar"), measure.vars = grep("^[A-Z]", names(dt), value = TRUE), variable.name = "upper", value.name = "upper_value") upper_melted[, match_key := tolower(gsub("_", "", upper))] # 合并数据集,得到最终结果 result <- lower_melted[upper_melted, on = .(foo, bar, lower = match_key), .(foo, bar, lower, lower_value, upper, upper_value)] # 查看结果 print(result)
执行后即可得到符合需求的长格式数据,例如b4对应的B_4不存在,会自动填充NA。
内容的提问来源于stack exchange,提问作者Jinglestar
相关产品推荐
相关产品推荐

