我开始越来越多地使用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的功能。 有人有建议吗?
由于
答案 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]
}
希望这有帮助。