from for循环适用于加速R
我正在运行一个for循环与两个矩阵。一个matrix(A)
具有〜100个字符串(例如,name1,name2,...,name100),并且只有一列。另一个matrix(B)
大于A
,包含值和字符串的行和列。在B
矩阵的某些地方,匹配了A
矩阵的每个名称。我想提取并堆叠匹配的整行,并在输出矩阵上使用矩阵A
的特定字符串。from for循环适用于加速R
所以,我下面运行,
output <- NULL
for(K in 1:nrow(A)){
print(K)
for(cc in 1:nrow(B)){
for(dd in 1:ncol(B)){
if(toupper(A[K])==toupper(B[cc,dd])){
output <- rbind(output,B[cc,])
}
}
}
}
但实在是太慢了。如何让循环在运行时间方面更高效?
这里的一些想法:
A <- matrix(c('a','b','c','d'), ncol=1)
B <- data.frame(z1=c('a','g','f','c'), z2=rnorm(4), z3=c('a','b','f','f'))
id <- apply(B, 2, function(x) A %in% x)
newB <- B[apply(id,1,sum)>0, ]
我得到“应用中的错误(kk,1,sum):object'kk'not found”? – Tommy
kk实际上是id。我编辑了我的回答 –
速度问题不是因为for-loop。 apply
可能会更慢。您需要预先标注目标对象并为索引分配值。
或者你需要考虑一个矢量化解决方案的喜欢...适用于Manuel的测试案例:
idx <- unique(which(toupper(as.matrix(B)) %in% toupper(A), arr.ind=TRUE) %% NROW(B))
idx[idx==0] <- 4
B[idx , ]
z1 z2 z3
1 a 1.5623285 a
4 c -1.2196311 f
2 g 0.2551535 b
你的表达是错误的。你必须包含A向量,并且我认为[,1]也是错误的。 –
未经测试的算法往往是错误的。我会放入一个有效的。关心速度竞争? –
你为什么分配idx [idx == 0]
这里有一个快速的解决方案,应该给予同样的输出你的:
set.seed(13)
A <- matrix(letters[1:5])
B <- matrix(sample(letters, 12, rep(T)), 4)
x <- match(toupper(A), toupper(B), nomatch=0L)
x <- (x[x>0L]-1L) %% nrow(B) + 1L
output <- B[x, , drop=FALSE]
它的工作原理是利用match
找到B中的(矢量)标w这里有一场比赛。然后它将这些索引转换为行索引,最后提取这些行。
..注意行B[2,]
在输出中包含两次 - 这真的是你想要的吗?如果没有,更改最后一行:
output <- B[unique(x), , drop=FALSE]
编辑一些时机。自从那个时代占据主导地位以来,我删除了toupper
的电话号码,@曼努埃尔拉蒙并没有这么称呼。请注意,我们所有的输出是不同的!所以一些调试可能是有保证的;-)
# Create huge A and B matrices
set.seed(13)
strs <- outer(letters, LETTERS, paste)
A <- matrix(strs)
B <- matrix(sample(strs, 1e7, rep(T)), 1e4)
# My solution: 0.24 secs
system.time({
x <- match(A, B, nomatch=0L)
x <- (x[x>0L]-1L) %% nrow(B) + 1L
output1 <- B[unique(x), , drop=FALSE]
})
# @DWin's solution: 0.91 secs
system.time({
idx <- unique(which(as.matrix(B) %in% A, arr.ind=TRUE) %% NROW(B))
idx[idx==0] <- 4
output2 <- B[idx, , drop=FALSE]
})
# @Manuel Ramon's solution: 0.89 secs
system.time({
id <- apply(B, 2, function(x) A %in% x)
output3 <- B[apply(id,1,sum)>0, ]
})
胡卡。我确信我的速度更快,尤其是自拉蒙有两个应用循环以来。谢谢,@Tommy。我们显然需要一组更好的调试用例。 –
B矩阵真的是矩阵吗?或者它是'data.frame'?一个“矩阵”只能有一种类型 - 所以所有的值都是字符串,然后... – Tommy