内容简介:http://stackoverflow.com/questions/14154952/finding-pattern-in-a-matrix-in-r
我有一个8 x n矩阵,例如
set.seed(12345) m <- matrix(sample(1:50, 800, replace=T), ncol=8) head(m) [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [1,] 37 15 30 3 4 11 35 31 [2,] 44 31 45 30 24 39 1 18 [3,] 39 49 7 36 14 43 26 24 [4,] 45 31 26 33 12 47 37 15 [5,] 23 27 34 29 30 34 17 4 [6,] 9 46 39 34 8 43 42 37
我想在矩阵中找到一个特定的模式,例如我想知道我在哪里可以找到一个37,其次在下一行10和29,后面是一个42
例如,在上述矩阵的第57:59行中
m[57:59,] [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [1,] *37 35 1 30 47 9 12 39 [2,] 5 22 *10 *29 13 5 17 36 [3,] 22 43 6 2 27 35 *42 50
A(可能无效率)的解决方案是获取包含37的所有行
sapply(1:nrow(m), function(x){37 %in% m[x,]})
然后使用几个循环来测试其他条件.
如何写一个有效的功能来做到这一点,这可以推广到任何用户给定的模式(不一定超过3行,可能的“空洞”,每行的值可变数量等).
编辑:回答各种意见
>我需要找到EXACT模式
>同一行中的顺序并不重要(如果使事情更简单,可以在每行中排序)
线必须相邻.
>我想得到返回的所有模式的(开始)位置(即,如果模式在矩阵中多次出现,我想要多个返回值).
>用户将通过GUI进入模式,我还没有决定如何.例如,要搜索上述模式,他可以写一些类似的东西
37; 10,29; 42
在哪里表示新行,并在同一行上分隔值.
同样,我们可能会寻找
50,51;;75;80,81
意思是行n中的50和51,行n 2中的75,行n 3中的80和81
这是一个广义的功能:
PatternMatcher <- function(data, pattern, idx = NULL) { p <- unlist(pattern[1]) if(is.null(idx)){ p <- unlist(pattern[length(pattern)]) PatternMatcher(data, rev(pattern)[-1], idx = Filter(function(n) all(p %in% intersect(data[n, ], p)), 1:nrow(data))) } else if(length(pattern) > 1) { PatternMatcher(data, pattern[-1], idx = Filter(function(n) all(p %in% intersect(data[n, ], p)), idx - 1)) } else Filter(function(n) all(p %in% intersect(data[n, ], p)), idx - 1) }
这是一个递归函数,它是在每次迭代中减少模式,并且只检查在上一次迭代中识别的行之后的行.列表结构允许以方便的方式传递模式:
PatternMatcher(m, list(37, list(10, 29), 42)) # [1] 57 PatternMatcher(m, list(list(45, 24, 1), 7, list(45, 31), 4)) # [1] 2 PatternMatcher(m, list(1,3)) # [1] 47 48 93
编辑:上面的函数的想法似乎很好:检查矢量模式[[1]]的所有行,并获得索引r1,然后检查行r1 1为模式[[2]]并获取r2等等,但它真的需要经历所有行的第一步很多时间.当然,每个步骤都需要很多时间. m<- 矩阵(样本(1:10,800,替换= T),ncol = 8),即当索引r1,r2,...没有太大变化时,这里是另一种方法,这里是PatternMatcher看起来非常相似,但是还有另一个函数matchRow用于查找具有向量的所有元素的行.
matchRow <- function(data, vector, idx = NULL){ if(is.null(idx)){ matchRow(data, vector[-1], as.numeric(unique(rownames(which(data == vector[1], arr.ind = TRUE))))) } else if(length(vector) > 0) { matchRow(data, vector[-1], as.numeric(unique(rownames(which(data[idx, , drop = FALSE] == vector[1], arr.ind = TRUE))))) } else idx } PatternMatcher <- function(data, pattern, idx = NULL) { p <- pattern[[1]] if(is.null(idx)){ rownames(data) <- 1:nrow(data) p <- pattern[[length(pattern)]] PatternMatcher(data, rev(pattern)[-1], idx = matchRow(data, p)) } else if(length(pattern) > 1) { PatternMatcher(data, pattern[-1], idx = matchRow(data, p, idx - 1)) } else matchRow(data, p, idx - 1) }
与以前的功能比较:
library(rbenchmark) bigM <- matrix(sample(1:50, 800000, replace=T), ncol=8) benchmark(PatternMatcher(bigM, list(37, c(10, 29), 42)), PatternMatcher(bigM, list(1, 3)), OldPatternMatcher(bigM, list(37, list(10, 29), 42)), OldPatternMatcher(bigM, list(1, 3)), replications = 10, columns = c("test", "elapsed")) # test elapsed # 4 OldPatternMatcher(bigM, list(1, 3)) 61.14 # 3 OldPatternMatcher(bigM, list(37, list(10, 29), 42)) 63.28 # 2 PatternMatcher(bigM, list(1, 3)) 1.58 # 1 PatternMatcher(bigM, list(37, c(10, 29), 42)) 2.02 verybigM1 <- matrix(sample(1:40, 8000000, replace=T), ncol=20) verybigM2 <- matrix(sample(1:140, 8000000, replace=T), ncol=20) benchmark(PatternMatcher(verybigM1, list(37, c(10, 29), 42)), PatternMatcher(verybigM2, list(37, c(10, 29), 42)), find.combo(verybigM1, convert.gui.input("37;10,29;42")), find.combo(verybigM2, convert.gui.input("37;10,29;42")), replications = 20, columns = c("test", "elapsed")) # test elapsed # 3 find.combo(verybigM1, convert.gui.input("37;10,29;42")) 17.55 # 4 find.combo(verybigM2, convert.gui.input("37;10,29;42")) 18.72 # 1 PatternMatcher(verybigM1, list(37, c(10, 29), 42)) 15.84 # 2 PatternMatcher(verybigM2, list(37, c(10, 29), 42)) 19.62
现在,模式参数应该像list(37,c(10,29),42)而不是列表(37,list(10,29),42)).最后:
fastPattern <- function(data, pattern) PatternMatcher(data, lapply(strsplit(pattern, ";")[[1]], function(i) as.numeric(unlist(strsplit(i, split = ","))))) fastPattern(m, "37;10,29;42") # [1] 57 fastPattern(m, "37;;42") # [1] 57 4 fastPattern(m, "37;;;42") # [1] 33 56 77
http://stackoverflow.com/questions/14154952/finding-pattern-in-a-matrix-in-r
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- C语言实现在杨氏矩阵中查找数字
- 机器学习 | SVD矩阵分解算法,对矩阵做拆分,然后呢?
- golang 算法-矩阵
- 彻底理解矩阵乘法
- [开源项目]矩阵数据的意义
- iphone – :CGAffineTransformInvert:奇异矩阵
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。