如何高效基于tibble_a的变量名提取tibble_b指定行对应值?
问题描述
我有两个tibble,tibble_a的每个取值都是tibble_b的列名,需要快速提取tibble_b指定行中、与tibble_a每行各列名对应的数值。但tibble_a行数多达数十万,当前用嵌套循环的方式效率极低,想找高效的实现方法。
现有数据结构:
# 记录每个case对应的tibble_b列名 tibble_a <- tribble( ~a, ~b, ~c, 4, 2, 5, 4, 3, 1, 2, 5, 5 ) # 存储不同变量对应的值 tibble_b <- tribble( ~`1`, ~`2`, ~`3`, ~`4`, ~`5`, 100, 112, 98, 107, 85, 71, 76, 97, 80, 15, 2, 61, 54, 37, 42 )
目标生成结果:
| a | b | c |
|---|---|---|
| 107 | 112 | 85 |
| 107 | 98 | 100 |
| 112 | 85 | 85 |
高效实现方法
方法1:向量化索引(最快,适合大行数)
直接利用R的向量化特性,把目标行转成命名向量后批量索引,完全避免循环,效率最高:
library(tibble) # 提取tibble_b的目标行(这里选第一行,可自行修改行号) target_row <- pull(tibble_b, 1) names(target_row) <- colnames(tibble_b) # 批量替换tibble_a的所有值 result <- tibble(apply(tibble_a, 2, function(col) target_row[as.character(col)]))
方法2:tidyverse重塑法(直观易读)
如果习惯tidyverse语法,用数据重塑的方式实现,内部同样是向量化操作,效率远高于循环:
library(dplyr) library(tidyr) # 将tibble_b的目标行转成长格式用于匹配 target_tbl <- tibble_b %>% slice(1) %>% # 选择目标行 pivot_longer(everything(), names_to = "col_name", values_to = "value") # 重塑tibble_a,匹配值后再转回宽格式 result <- tibble_a %>% mutate(row_id = row_number()) %>% pivot_longer(-row_id, names_to = "col", values_to = "col_name") %>% mutate(col_name = as.character(col_name)) %>% left_join(target_tbl, by = "col_name") %>% select(row_id, col, value) %>% pivot_wider(names_from = col, values_from = value) %>% select(-row_id)
方法3:data.table极致高效法(超大数据量首选)
如果数据量达到百万级,data.table的操作速度会更有优势:
library(data.table) # 转换为data.table对象 dt_a <- as.data.table(tibble_a) dt_b <- as.data.table(tibble_b) # 提取目标行的命名向量 target_vec <- unlist(dt_b[1, ]) names(target_vec) <- colnames(dt_b) # 批量替换 result <- dt_a[, lapply(.SD, function(col) target_vec[as.character(col)])] # 可选:转回tibble格式 result <- as_tibble(result)
内容的提问来源于stack exchange,提问作者SiliconFern
相关产品推荐
相关产品推荐

