You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用DataFrame的行列组合在另一个DataFrame中高效取值?

高效从Data2中匹配Data1对应的数值(替代循环方案)

需要用Data1中ID与Date的组合,作为行、列索引在Data2中提取对应数值。现有循环实现因数据集过大运行过慢,寻求优化方案。

示例数据

Data1

#   ID       Date
# 1  A 2022-02-01
# 2  B 2022-02-02
# 3  C 2022-02-03
# 4  D 2022-02-04
# 5  E 2022-02-05
# 6  F 2022-02-06
# 7  G 2022-02-07
# 8  H 2022-02-08

Data2

#   ID X2022.02.01 X2022.02.02 X2022.02.03 X2022.02.04 X2022.02.05 X2022.02.06 X2022.02.07 X2022.02.08
# 1  A           1           9          17          25          33          41          49          57
# 2  B           2          10          18          26          34          42          50          58
# 3  C           3          11          19          27          35          43          51          59
# 4  D           4          12          20          28          36          44          52          60
# 5  E           5          13          21          29          37          45          53          61
# 6  F           6          14          22          30          38          46          54          62
# 7  G           7          15          23          31          39          47          55          63
# 8  H           8          16          24          32          40          48          56          64

期望结果

#   ID       Date Value
# 1  A 2022-02-01     1
# 2  B 2022-02-02    10
# 3  C 2022-02-03    19
# 4  D 2022-02-04    28
# 5  E 2022-02-05    37
# 6  F 2022-02-06    46
# 7  G 2022-02-07    55
# 8  H 2022-02-08    64

现有低效循环代码

for (i in 1:nrow(Data1)) {
  a <- Data1[[1]][[i]]
  b <- Data1[[2]][[i]]
  c <- Data2[b, a]
  Data1$Value[i] <- c
}

数据定义代码

Data1 <- data.frame(ID=c("A", "B", "C", "D", "E", "F", "G", "H"), 
                    Date=c("2022-02-01", "2022-02-02", "2022-02-03", "2022-02-04",
                           "2022-02-05", "2022-02-06","2022-02-07", "2022-02-08"))
Data2 <- data.frame(ID=c("A", "B", "C", "D", "E", "F", "G", "H"), 
                    "2022-02-01"=c(1:8),
                    '2022-02-02'=c(9:16),
                    '2022-02-03'=c(17:24),
                    '2022-02-04'=c(25:32),
                    '2022-02-05'=c(33:40),
                    '2022-02-06'=c(41:48),
                    '2022-02-07'=c(49:56),
                    '2022-02-08'=c(57:64))

优化方案

方案1:Tidyverse 长格式转换+匹配

将Data2从宽格式转为ID、Date、Value的长格式,再与Data1合并,适合结构化数据处理:

library(tidyverse)

# 转换Data2为长格式,处理列名的X前缀和点号
Data2_long <- Data2 %>%
  pivot_longer(cols = -ID, 
               names_to = "Date", 
               values_to = "Value") %>%
  mutate(Date = str_replace(Date, "^X", "") %>% str_replace_all("\\.", "-"))

# 合并Data1与转换后的Data2
result <- Data1 %>%
  left_join(Data2_long, by = c("ID", "Date"))

方案2:Base R 向量化索引

利用向量化操作直接提取值,避免循环带来的性能损耗:

# 将Data2的行名设为ID,方便按ID索引
rownames(Data2) <- Data2$ID
# 把Data1的Date转换成Data2对应的列名格式(X+点号替换横杠)
Data1$col_name <- paste0("X", str_replace_all(Data1$Date, "-", "\\."))
# 向量化提取对应值
Data1$Value <- Data2[Data1$ID, Data1$col_name]
# 可选:删除临时生成的col_name列
Data1 <- Data1[, !names(Data1) %in% "col_name"]

方案3:Data.table 高效匹配

针对超大规模数据集,data.table的键连接性能优势显著:

library(data.table)

# 转换为data.table格式
setDT(Data1)
setDT(Data2)

# Data2转长格式并处理日期列名
Data2_long <- melt(Data2, id.vars = "ID", variable.name = "Date", value.name = "Value")
Data2_long[, Date := gsub("^X", "", Date)][, Date := gsub("\\.", "-", Date)]

# 设置键并执行匹配
setkey(Data1, ID, Date)
setkey(Data2_long, ID, Date)
result <- Data2_long[Data1]

内容的提问来源于stack exchange,提问作者user19479634

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 13:50:45