迭代两个data.tables'行

时间:2015-06-30 16:08:32

标签: r data.table

我开始越来越多地使用R,来自C / C ++。出于这个原因,我经常在使用R的数据结构时发现自己正在考虑àlaC ++

这里我有两个data.tables,我必须迭代并根据第1列表B w.r.t更新表A中第1列和第2列的值,其值为表2中的第2列。表A中的第1列和第2列。

很抱歉这个令人困惑的描述。我试着让它变得更好

我有两个数据表(行数不同,因为它们实际上可能不同):

塔巴

     Col1     Col2
1:   TP53     CD68
2:   TP53    MPDU1
3:   TP53     PHF2
4:   TP53 KIAA0753
5:   CD68    ZBTB4
6:   CD68     CHD3
7:  MPDU1    ZBTB4
8:  MPDU1     CHD3
9:  MPDU1   SLC2A4
10: MPDU1     YBX2
11: MPDU1    AURKB
12: MPDU1 TMEM132B
13:  PHF2 C9orf129
14:  PHF2    CDH23
15:  PHF2   PTPDC1

和TabB:

       Col3 Col4
1:   ADAM32  0
2:   ADARB2  1
3:    AGBL2  2
4:   ALOX12  3
5:  ANKRD46  4
6:    APOL1  5
7:    APOOL  6
8:     ASPA  7
9:      AUH  8
10:   AURKB  9
11:   AUTS2 10
12:    BAAT 11

基本上,我想将TabA中的Col1和Col2与TabB中的Col3进行比较:如果它们相等,则将该字符串替换为TabB的Col4中的数字。

我的方法,绝对是C风格:

for(i in 1:nrow(TabA)) {
    for(j in 1:nrow(TabB)) {
        if(TabA$Col1[i] == TabB$Col3[j]) { 
            TabA$Col1[i] <- TabB$Col4[j] 
        }
        if(TabA$Col2[i] == TabB$Col3[j]) { 
            TabA$Col2[i] <- TabB$Col4[j] 
        }
    }
}

这可以按预期工作,但我非常确定有一种更优雅(更有效)的方法,利用data.table的功能。 有人有建议吗?

由于

4 个答案:

答案 0 :(得分:5)

如果您使用data.table原始问题(在更改问题的大量修改之前)可以这样做:

TabA <- data.table(Col1 = sample(LETTERS, 15), Col3 = rnorm(15))
TabB <- data.table(Col2 = sample(LETTERS, 15), Col4 = rnorm(15))
setkey(TabA, Col1)
setkey(TabB, Col2)
TabA
# shows TabA before changing it
TabA[TabB, Col3 := Col4]

我仍然觉得data.table的语法有点奇怪,因为当函数不修改它们的参数时,它与R中的标准行为不同。另一方面,它可以实现简洁,高效,快速的代码。

重写问题的解决方案

请注意,您的示例数据无用 - TabA$Col1中没有TabB$Col3的匹配项。无论如何,这可以通过几种方式解决。

使用data.table :=运营商:

TabA[Col1 %in% TabB$Col3, Col1 := with(TabB, as.character(Col4[na.omit(match(Col1, Col3))]))]
TabA[Col2 %in% TabB$Col3, Col2 := with(TabB, as.character(Col4[na.omit(match(Col2, Col3))]))]

使用基本R语法(也适用于data.frame):

TabA$Col1[TabA$Col1 %in% TabB$Col3] <- TabB$Col4[match(TabA$Col1[TabA$Col1 %in% TabB$Col3], TabB$Col3)]
TabA$Col2[TabA$Col2 %in% TabB$Col3] <- TabB$Col4[match(TabA$Col2[TabA$Col2 %in% TabB$Col3], TabB$Col3)]

使用setkey和join:

TabA[, Index := 1:nrow(TabA)]
setkey(TabA, Col1)
TabA[TabB, nomatch = 0, Col1 := as.character(Col4)]
setkey(TabA, Col2)
TabA[TabB, nomatch = 0, Col2 := as.character(Col4)]
setkey(TabA, Index)
TabA[, Index := NULL]

所有这些都假设Col1和Col2中的某些项目不匹配。如果不是这样,可以优化代码。这也是Col4必须被胁迫的原因。

答案 1 :(得分:1)

当我想迭代抛出by=1:nrow(DT)的每一行时,我通常会使用datatabe

library(data.table)

TabA <- data.table(Col1=c('A', 'B', 'C', 'D'), Col2=c('B', 'A', 'D', 'C'))
TabB <- data.table(Col3=c('A', 'B', 'C'), Col4=c(1, 2, 3))

TabA[, .(Col1=as.character(ifelse(nrow(TabB[Col3==Col1]) > 0, TabB[Col3==Col1]$Col4, Col1)), 
         Col2=as.character(ifelse(nrow(TabB[Col3==Col2]) > 0, TabB[Col3==Col2]$Col4, Col2))
         ), 
     by=1:nrow(TabA)][, .(Col1, Col2)]

TabA[, `:=`(Col1=as.character(ifelse(nrow(TabB[Col3==Col1]) > 0, TabB[Col3==Col1]$Col4, Col1)), 
            Col2=as.character(ifelse(nrow(TabB[Col3==Col2]) > 0, TabB[Col3==Col2]$Col4, Col2))
            ), 
     by=1:nrow(TabA)]

答案 2 :(得分:0)

由于我没有你的数据,我做了一个小例子,但我这就是你要找的东西:

x<- c("a","b","c","d") 
y<-c("a","d","e","f")
z<-c("z1","z2","z3","z4")
x[x %in% y]<-z[x %in% y]

答案 3 :(得分:0)

以下是一个仅使用基础R的建议。

the_equals <- TabA$Col1[which(TabA$Col1 %in% TabB$Col3)]
nequals <- length(the_equals)
if(nequals>0) {
 idx1 <- lapply(1:nequals, function(x) which(TabA$Col1==the_equals[x]))
 idx2 <- lapply(1:nequals, function(x) which(TabB$Col3==the_equals[x]))
 Col2_new <- sapply(1:nequals, function(x) TabB$Col4[idx2[[x]][1]])
 for(i in 1:nequals) TabA$Col2[idx1[[i]]] <- Col2_new[i]
}

希望这有帮助。