在data.table中使用不同的键进行多次合并

时间:2017-12-14 02:56:23

标签: r merge data.table left-join

我有两个数据表。

第一个数据表有很多行,包含一个主名称(name1),相关名称(names2到names5)和一个数字列功能。相关名称有限(例如此处为5),每个名称​​ i 在相同的有限集中取值(例如,在字符串组W = {num1,num2,num3}中,大小为3这里)。

这是df

的头部的一个例子
   name1 name2 name3 name4 name5        feat
1:  num1  num2  num3  num3  num1  0.88010416
2:  num2  num1  num2  num1  num1  1.37001035
3:  num2  num1  num1  num1  num1 -1.68732684
4:  num2  num2  num3  num1  num1 -0.62743621
5:  num3  num2  num1  num1  num1  0.01831663

第二个数据表是"链接"具有数字特征feat_A和feat_B的W元素之间的表格。以下是此类df_alt

的头部示例
   name      feat_A      feat_B
1: num1 -0.03763026 0.011395161
2: num2  0.72397606 0.009859946
3: num3 -0.49673886 0.678271423

将df与df_alt合并的最有效方法是什么? 我想为每个列名 i 合并df和df_alt,即获取(注意行不按顺序排列):

   name1 name2 name3 name4 name5        feat     feat_A1     feat_A2
1:  num2  num1  num1  num1  num1 -1.68732684  0.72397606 -0.03763026
2:  num3  num2  num1  num1  num1  0.01831663 -0.49673886  0.72397606
3:  num2  num1  num2  num1  num1  1.37001035  0.72397606 -0.03763026
4:  num2  num2  num3  num1  num1 -0.62743621  0.72397606  0.72397606
5:  num1  num2  num3  num3  num1  0.88010416 -0.03763026  0.72397606
       feat_A3     feat_A4     feat_A5     feat_B1     feat_B2     feat_B3
1: -0.03763026 -0.03763026 -0.03763026 0.009859946 0.011395161 0.011395161
2: -0.03763026 -0.03763026 -0.03763026 0.678271423 0.009859946 0.011395161
3:  0.72397606 -0.03763026 -0.03763026 0.009859946 0.011395161 0.009859946
4: -0.49673886 -0.03763026 -0.03763026 0.009859946 0.009859946 0.678271423
5: -0.49673886 -0.49673886 -0.03763026 0.011395161 0.009859946 0.678271423
      feat_B4    feat_B5
1: 0.01139516 0.01139516
2: 0.01139516 0.01139516
3: 0.01139516 0.01139516
4: 0.01139516 0.01139516
5: 0.67827142 0.01139516

我需要多次执行此合并(df固定和df_alt变化),因此成本效率很重要......

我目前最好的方法是进行包含合并的循环,但我想避免这种循环

for(i in 1:5) {
  df_alt_i = df_alt
  names(df_alt_i) = paste0(names(df_alt), i)
  df = merge(df, df_alt_i, by=paste0("name", i), all.x = TRUE)
}
df = df[, c(paste0("name", 1:5), "feat", 
            paste0("feat_A", 1:5), paste0("feat_B", 1:m)), with = FALSE]

有没有聪明的方法来完成这项任务?

我尝试使用dplyr的left_join(在另一篇文章中看到),但它比当前方法慢得多。我也考虑过Reduce(在另一篇文章中),但我不知道如何有效地使用它,因为在循环中使用相同的df_alt。我想过将名称特征转换为矩阵,然后用df_alt中的相关元素替换每个元素,但没有取得多大成功。

这里有完全可复制的代码:

library(data.table)
m = 5
nrow = 5
set.seed(1234)

sample_name = function(nrow) {
  sample(c("num1", "num2", "num3"), nrow, replace = TRUE)
}

df = data.table(name1 = sample_name(nrow),
                name2 = sample_name(nrow),
                name3 = sample_name(nrow),
                name4 = sample_name(nrow),
                name5 = sample_name(nrow),
                feat = rnorm(nrow))

df_alt = data.table(name = c("num1", "num2", "num3"),
                    feat_A = rnorm(3),
                    feat_B = rnorm(3))

## Merge approach
for(i in 1:m) {
  df_alt_i = df_alt
  names(df_alt_i) = paste0(names(df_alt), i)
  df = merge(df, df_alt_i, by=paste0("name", i), all.x = TRUE)
}
df = df[, c(paste0("name", 1:m), "feat", 
            paste0("feat_A", 1:m), paste0("feat_B", 1:m)), 
        with = FALSE]

## Left join approach (slow)
library(dplyr)
left_join(df, df_alt, by=c("name1" = "name")) %>%
  left_join(., df_alt, by=c("name2" = "name")) %>%
  left_join(., df_alt, by=c("name3" = "name")) %>%
  left_join(., df_alt, by=c("name4" = "name")) %>%
  left_join(., df_alt, by=c("name5" = "name"))

0 个答案:

没有答案