如何将R中data.table的melt与dcast转换为dplyr的pivot_longer与pivot_wider?
将data.table的melt/dcast逻辑转换为dplyr的pivot_longer/pivot_wider
示例数据
input_ds_wt = structure(list(id = c(1, 2, 3, 4, 5, 6), wt.mean_v1 = c(1, 1, 1.3, 2.3, 1, 0), wt.mean_v2 = c(0.8, 0.2, 0.8, 0.2, 0.8, 0.2), wt.SE_v1 = c(0.1, 0.01, 0.2, 0.02, 0.3, 0.03), wt.SE_v2 = c(0.03, 0.3, 0.01, 0.1, 0.4, 0.04), RSE_v1 = c(0.1, 0.01, 0.153846153846154, 0.00869565217391304, 0.3, Inf), RSE_v2 = c(0.0375, 1.5, 0.0125, 0.5, 0.5, 0.2)), class = "data.frame", row.names = c(NA, -6L))
数据预览:
id wt.mean_v1 wt.mean_v2 wt.SE_v1 wt.SE_v2 RSE_v1 RSE_v2 1 1 1.0 0.8 0.10 0.03 0.100000000 0.0375 2 2 1.0 0.2 0.01 0.30 0.010000000 1.5000 3 3 1.3 0.8 0.20 0.01 0.153846154 0.0125 4 4 2.3 0.2 0.02 0.10 0.008695652 0.5000 5 5 1.0 0.8 0.30 0.40 0.300000000 0.5000 6 6 0.0 0.2 0.03 0.04 Inf 0.2000
原data.table实现代码
library(data.table) setDT(input_ds_wt) #1. 重塑拆分版本信息 x <- melt(input_ds_wt, id.vars = "id") x[, c("variable", "version") := tstrsplit(variable, split = "_") ] #2. 按版本展开变量 x <- dcast(x, id + version ~ variable, value.var = "value") #3. 计算suppress列 x[, suppress := fifelse(RSE < 0.3 & wt.mean > 0.9, 0, 1) ] #4. 重新融合并拼接变量与版本名 x <- melt(x, id.vars = c("id", "version") ) x[, variable := paste(variable, version, sep = "_") ] #5. 恢复原始数据结构 x <- dcast(x, id ~ variable, value.var = "value")
运行结果:
Key: <id> id RSE_v1 RSE_v2 suppress_v1 suppress_v2 wt.SE_v1 wt.SE_v2 wt.mean_v1 wt.mean_v2 <num> <num> <num> <num> <num> <num> <num> <num> <num> 1: 1 0.100000000 0.0375 0 1 0.10 0.03 1.0 0.8 2: 2 0.010000000 1.5000 0 1 0.01 0.30 1.0 0.2 3: 3 0.153846154 0.0125 0 1 0.20 0.01 1.3 0.8 4: 4 0.008695652 0.5000 0 1 0.02 0.10 2.3 0.2 5: 5 0.300000000 0.5000 1 1 0.30 0.40 1.0 0.8 6: 6 Inf 0.2000 1 1 0.03 0.04 0.0 0.2
dplyr分步实现
第一步:拆分变量与版本(已完成)
library(dplyr) library(tidyr) input_ds_wt <- input_ds_wt %>% as_tibble() # 1. 重塑拆分版本信息 step1 <- input_ds_wt %>% pivot_longer(cols = !id, names_to = c("variable", "version"), names_pattern = "(.*)_(.*)")
step1预览:
# A tibble: 36 x 4 id variable version value <dbl> <chr> <chr> <dbl> 1 1 wt.mean v1 1 2 1 wt.mean v2 0.8 3 1 wt.SE v1 0.1 4 1 wt.SE v2 0.03 5 1 RSE v1 0.1 6 1 RSE v2 0.0375 7 2 wt.mean v1 1 8 2 wt.mean v2 0.2 9 2 wt.SE v1 0.01 10 2 wt.SE v2 0.3
第二步:按版本展开变量(对应dcast)
使用pivot_wider,指定分组列id和version,将variable列的值作为新列名,value列的值作为对应列的内容,即可实现dcast的效果:
# 2. 按版本展开变量 step2 <- step1 %>% pivot_wider(id_cols = c(id, version), names_from = variable, values_from = value)
step2预览:
# A tibble: 12 x 5 id version RSE wt.SE wt.mean <dbl> <chr> <dbl> <dbl> <dbl> 1 1 v1 0.1 0.1 1 2 1 v2 0.0375 0.03 0.8 3 2 v1 0.01 0.01 1 4 2 v2 1.5 0.3 0.2 5 3 v1 0.154 0.2 1.3 6 3 v2 0.0125 0.01 0.8 7 4 v1 0.00870 0.02 2.3 8 4 v2 0.5 0.1 0.2 9 5 v1 0.3 0.3 1 10 5 v2 0.5 0.4 0.8 11 6 v1 Inf 0.03 0 12 6 v2 0.2 0.04 0.2
完整dplyr流程
将所有步骤串联,得到与data.table完全一致的结果:
final_result <- input_ds_wt %>% as_tibble() %>% # 1. 拆分变量与版本 pivot_longer(cols = !id, names_to = c("variable", "version"), names_pattern = "(.*)_(.*)") %>% # 2. 按版本展开变量 pivot_wider(id_cols = c(id, version), names_from = variable, values_from = value) %>% # 3. 计算suppress列 mutate(suppress = ifelse(RSE < 0.3 & wt.mean > 0.9, 0, 1)) %>% # 4. 重新融合并拼接变量名与版本 pivot_longer(cols = !c(id, version), names_to = "variable") %>% mutate(variable = paste(variable, version, sep = "_")) %>% # 5. 恢复原始数据结构 pivot_wider(id_cols = id, names_from = variable, values_from = value) %>% # 按id排序,匹配data.table结果顺序 arrange(id)
最终结果预览:
# A tibble: 6 x 9 id RSE_v1 RSE_v2 suppress_v1 suppress_v2 wt.SE_v1 wt.SE_v2 wt.mean_v1 wt.mean_v2 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 0.1 0.0375 0 1 0.1 0.03 1 0.8 2 2 0.01 1.5 0 1 0.01 0.3 1 0.2 3 3 0.154 0.0125 0 1 0.2 0.01 1.3 0.8 4 4 0.0087 0.5 0 1 0.02 0.1 2.3 0.2 5 5 0.3 0.5 1 1 0.3 0.4 1 0.8 6 6 Inf 0.2 1 1 0.03 0.04 0 0.2
内容的提问来源于stack exchange,提问作者abrar
相关产品推荐
相关产品推荐

