R 在较大的二维表格中查找二维表格
我的问题如下: 我正在寻找在较大的表中查找2D表的列和行索引的最快方法。小表的大小为nxm,在j>n和k>m的较大的jxk表中可以出现多次。我一直在尝试使用“data.table”包实现这一点,但失败了。我的问题与下面的问题非常相似: 但我希望在R中快速完成这项工作。在使用for循环实现蛮力方法之前,我想听听您的看法。请注意,表中可能有数字和字符串 如果你需要一个例子。你可以考虑我需要搜索下面的数据帧:R 在较大的二维表格中查找二维表格,r,performance,data.table,R,Performance,Data.table,我的问题如下: 我正在寻找在较大的表中查找2D表的列和行索引的最快方法。小表的大小为nxm,在j>n和k>m的较大的jxk表中可以出现多次。我一直在尝试使用“data.table”包实现这一点,但失败了。我的问题与下面的问题非常相似: 但我希望在R中快速完成这项工作。在使用for循环实现蛮力方法之前,我想听听您的看法。请注意,表中可能有数字和字符串 如果你需要一个例子。你可以考虑我需要搜索下面的数据帧: data.frame(A=c(1.7,1.5,1.7),B=c(0.3,0.3,0.2),C
data.frame(A=c(1.7,1.5,1.7),B=c(0.3,0.3,0.2),C=c("setosa","setosa","setosa"))
您必须在“iris”数据框中搜索。输出答案是:
第19行和第3列。基于:
库(dplyr)
#检查相等时出现的因素问题,请改为使用字符串
df1%
dplyr::mutate_if(is.factor,as.character)
df%
dplyr::mutate_if(is.factor,as.character)
#查找df1左上角的所有匹配项
点击次数基于:
库(dplyr)
#检查相等时出现的因素问题,请改为使用字符串
df1%
dplyr::mutate_if(is.factor,as.character)
df%
dplyr::mutate_if(is.factor,as.character)
#查找df1左上角的所有匹配项
点击数据。表
对于关系表来说很快,但是基本的矩阵
非常快。我的建议是将表存储为矩阵,并使用更简单的子集来比较子矩阵
从一些示例数据开始:bigmat
是我们将在其中查找匹配项的大矩阵,smallmat\u in
是bigmat
的子矩阵,smallmat\u out
是不在bigmat
内的矩阵
bigmat <- matrix(c(1:50, 1:50), nrow = 10)
smallmat_in <- bigmat[6:8, 2:3]
smallmat_out <- smallmat_in
smallmat_out[6] <- 0
bigmat
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 1 11 21 31 41 1 11 21 31 41
# [2,] 2 12 22 32 42 2 12 22 32 42
# [3,] 3 13 23 33 43 3 13 23 33 43
# [4,] 4 14 24 34 44 4 14 24 34 44
# [5,] 5 15 25 35 45 5 15 25 35 45
# [6,] 6 16 26 36 46 6 16 26 36 46
# [7,] 7 17 27 37 47 7 17 27 37 47
# [8,] 8 18 28 38 48 8 18 28 38 48
# [9,] 9 19 29 39 49 9 19 29 39 49
# [10,] 10 20 30 40 50 10 20 30 40 50
smallmat_in
# [,1] [,2]
# [1,] 16 26
# [2,] 17 27
# [3,] 18 28
smallmat_out
# [,1] [,2]
# [1,] 16 26
# [2,] 17 27
# [3,] 18 0
smallmat_in
和smallmat_out
仅在最后一个元素上不同,因此它们的第一个元素具有相同的匹配项。接下来,我们将定义一个函数,它接受一个小矩阵(small
)、一个大矩阵(big
)和一个行-列对(big\u first\u index
)。如果行-列对是与small
匹配的big
子矩阵的左上角,则返回TRUE
。否则,FALSE
is_matrix_match <- function(small, big, big_first_index) {
row_indices <- seq(big_first_index[1], by = 1, length.out = nrow(small))
col_indices <- seq(big_first_index[2], by = 1, length.out = ncol(small))
all(small == big[row_indices, col_indices])
}
is_matrix_match(smallmat_in, bigmat, c(6, 2))
# [1] TRUE
is_matrix_match(smallmat_out, bigmat, c(6, 2))
# [1] FALSE
因为这是一个概念证明,所以它没有任何检查(比如确保big
实际上大于small
)。在生产环境中拥有这些将是很好的
我不知道您使用的矩阵有多大,但以下是我对更大矩阵的一些速度测量:
hugemat <- matrix(rep_len(1:7, 1e7), nrow = 10)
format(object.size(hugemat), "MB")
# [1] "38.1 Mb"
huge_submat <- hugemat[2:9, 200:300]
huge_not_submat <- huge_submat
huge_not_submat[] <- 1
system.time(in_matrix(huge_submat, hugemat))
# user system elapsed
# 10.51 0.00 10.53
system.time(in_matrix(huge_not_submat, hugemat))
# user system elapsed
# 10.62 0.00 10.69
hugematdata.table
对于关系表来说非常快,但是基本的矩阵
非常快。我的建议是将表存储为矩阵,并使用更简单的子集来比较子矩阵
从一些示例数据开始:bigmat
是我们将在其中查找匹配项的大矩阵,smallmat\u in
是bigmat
的子矩阵,smallmat\u out
是不在bigmat
内的矩阵
bigmat <- matrix(c(1:50, 1:50), nrow = 10)
smallmat_in <- bigmat[6:8, 2:3]
smallmat_out <- smallmat_in
smallmat_out[6] <- 0
bigmat
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 1 11 21 31 41 1 11 21 31 41
# [2,] 2 12 22 32 42 2 12 22 32 42
# [3,] 3 13 23 33 43 3 13 23 33 43
# [4,] 4 14 24 34 44 4 14 24 34 44
# [5,] 5 15 25 35 45 5 15 25 35 45
# [6,] 6 16 26 36 46 6 16 26 36 46
# [7,] 7 17 27 37 47 7 17 27 37 47
# [8,] 8 18 28 38 48 8 18 28 38 48
# [9,] 9 19 29 39 49 9 19 29 39 49
# [10,] 10 20 30 40 50 10 20 30 40 50
smallmat_in
# [,1] [,2]
# [1,] 16 26
# [2,] 17 27
# [3,] 18 28
smallmat_out
# [,1] [,2]
# [1,] 16 26
# [2,] 17 27
# [3,] 18 0
smallmat_in
和smallmat_out
仅在最后一个元素上不同,因此它们的第一个元素具有相同的匹配项。接下来,我们将定义一个函数,它接受一个小矩阵(small
)、一个大矩阵(big
)和一个行-列对(big\u first\u index
)。如果行-列对是与small
匹配的big
子矩阵的左上角,则返回TRUE
。否则,FALSE
is_matrix_match <- function(small, big, big_first_index) {
row_indices <- seq(big_first_index[1], by = 1, length.out = nrow(small))
col_indices <- seq(big_first_index[2], by = 1, length.out = ncol(small))
all(small == big[row_indices, col_indices])
}
is_matrix_match(smallmat_in, bigmat, c(6, 2))
# [1] TRUE
is_matrix_match(smallmat_out, bigmat, c(6, 2))
# [1] FALSE
因为这是一个概念证明,所以它没有任何检查(比如确保big
实际上大于small
)。在生产环境中拥有这些将是很好的
我不知道您使用的矩阵有多大,但以下是我对更大矩阵的一些速度测量:
hugemat <- matrix(rep_len(1:7, 1e7), nrow = 10)
format(object.size(hugemat), "MB")
# [1] "38.1 Mb"
huge_submat <- hugemat[2:9, 200:300]
huge_not_submat <- huge_submat
huge_not_submat[] <- 1
system.time(in_matrix(huge_submat, hugemat))
# user system elapsed
# 10.51 0.00 10.53
system.time(in_matrix(huge_not_submat, hugemat))
# user system elapsed
# 10.62 0.00 10.69
hugemat软件包kit
中的函数fpos
返回一个较大矩阵中一个小矩阵的位置。它也适用于向量。将data.frame转换为矩阵,然后使用fpos
。请注意,该函数是用C实现的,因此速度应该很快。packagekit
中的函数fpos
会返回较大矩阵中的小矩阵位置。它也适用于向量。将data.frame转换为矩阵,然后使用fpos
。请注意,该函数是用C实现的,因此速度应该很快。请看一看,如果它是您要查找的,我会将其标记为dup,但您不应删除它,因为它以不同的方式被询问,可能会帮助其他人找到它。@hrbrmstr,谢谢您的回复。问题在某种程度上相似,但不确定是否相同。在您提供的链接中,有2个答案不起作用或不完整,Rcpp答案返回错误。我试图调试它,但没有成功。请看一看,如果它是您想要的,我会将它标记为dup,但您不能删除它,因为它以不同的方式被询问,可能会帮助其他人找到它。@hrbrmstr,谢谢您的回复。问题在某种程度上相似,但不确定是否相同。在您提供的链接中,有2个答案不起作用或不完整,Rcpp答案返回错误。我试着调试它,但没有成功。谢谢你的回复。我发现在大桌子上比较慢,不过我会接受你的答案。我会在你提供的基础上尝试更快的实现。谢谢你的回复。我发现在大桌子上比较慢,不过我会接受你的答案。我将尝试根据您提供的内容更快地实现某些功能。使用矩阵可能是个好主意,但您如何处理OP的要求:请注意,在表中,您可能有数字和字符串。@Uwe我的解决方案不依赖数字比较,因此它也适用于字符矩阵。任何数字数据都可以转换为字符。@Nath