2016-12-04 1 views
1

입니다. 이것은 쉬운 해결책이있을 수 있지만 여전히 찾을 수는 없습니다. 나는 크기 M1 = (4, 2000000)과 M2 = (4,209)의 두 행렬을 가지고 있습니다. M2의 각 열과 M1의 모든 열 사이의 요소 교차 길이를 찾고 싶습니다.두 행렬 간의 요소 교차점이

M2 한 열에 대해 I가 수행

TMP는 M2의 첫 번째 열이다
res <- apply(M1, 2, function(x) length(intersect(tmp, x))) 

.

약 30 초가 소요됩니다. M2의 모든 열에 대한 계산 속도를 높이려면 다음을 수행하십시오.

list <- foreach(k=1:ncol(M2)) %dopar% { 

    tmp <- M2[,k] 
    res <- apply(M1, 2, function(x) length(intersect(tmp, x))) 
} 

약 20 분이 소요됩니다.

적용 기능으로 foreach 루프를 피할 수있는 방법이 있습니까?

감사합니다.

+0

그것은 보인다는'tcrossprod (테이블 (COL (M1), M1)은> 0L는 테이블 (COL (M2), M2)> 0L)는 '인 당신이하고있는 것과 비슷합니다. 'table (col (M1), M1)> 0L'은보다 효율적인'replace (행렬 (0L, ncol (M1), max (M1)), cbind (rep (1 : ncol (M1), each = nrow (M1)), c (M1)), 1L)'또는 데이터의 크기를 고려한 희소 행렬 사용을 고려하십시오. –

답변

3

갖는 데이터 :

set.seed(991) 
M1 = matrix(sample(5, 50, TRUE), 5) 
M2 = matrix(sample(5, 25, TRUE), 5) 

솔루션의 반환 : 어떤

ans1 = tcrossprod(table(col(M1), M1) > 0L, table(col(M2), M2) > 0L) 

반환

op = sapply(1:ncol(M2), 
      function(k) apply(M1, 2, function(x) length(intersect(M2[, k], x)))) 
op 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 3 1 3 2 3 
# [2,] 3 2 3 3 4 
# [3,] 2 2 2 2 3 
# [4,] 2 3 3 2 3 
# [5,] 2 2 3 1 2 
# [6,] 2 2 2 2 3 
# [7,] 2 3 3 2 3 
# [8,] 2 2 3 3 3 
# [9,] 2 2 3 3 3 
#[10,] 1 3 2 1 2 

이다.우리가 발행 수의 수를 필요로하지 않기 때문에

all.equal(op, ans1, check.attributes = FALSE) 
#[1] TRUE 

, 우리는 단순 매트릭스 조작으로 table에 고가의 호출을 대체 할 수 있습니다 : 귀하의 경우를 들어

m1 = matrix(0L, ncol(M1), max(M1)) 
m1[cbind(rep(1:ncol(M1), each = nrow(M1)), c(M1))] = 1L 

m2 = matrix(0L, ncol(M2), max(M2)) 
m2[cbind(rep(1:ncol(M2), each = nrow(M2)), c(M2))] = 1L 
ans2 = tcrossprod(m1, m2) 

all.equal(op, ans2) 
#[1] TRUE 

를,하여 시작하는 것이 더 적절한 것 같다 메모리 제약 조건 방지 할 수있는 기회가 있으면 희소 도표화 :

library(Matrix) 
sm1 = sparseMatrix(x = 1L, 
        i = rep(1:ncol(M1), each = nrow(M1)), 
        j = M1, 
        use.last.ij = TRUE) 
sm2 = sparseMatrix(x = 1L, 
        i = rep(1:ncol(M2), each = nrow(M2)), 
        j = M2, 
        use.last.ij = TRUE) 
ans3 = tcrossprod(sm1, sm2) 

all.equal(op, as.matrix(ans3), check.attributes = FALSE) 
#[1] TRUE 
+0

이제 모두가 벤치 마크를 추가하여 모든 사람들이 당신의 멋진 솔루션을 더 잘 평가할 수있게 될 것입니다 : P –

+1

@DavidArenburg :'ncol (M1) * 길이 (unique.default (M1))'tabulation은 벤치마킹을 크리스마스 눈송이로 바꾸는 '메모리를 할당 할 수 없습니다'라는 코멘트를 가져올 수도 있습니다. :-) –

+0

그래, 그게 벡터화 된 솔루션의 주된 문제라고 생각합니다. 단순한 루프에 비해 메모리가 효율적이지 않습니다. . –

1

이 행렬 크기를 감안할 때, 당신은 더 빠르게 처리 될 수있는이 할 수있는 :

apply(m2, 2, function(x) colSums(m1==x[1] | m1==x[2] | m1==x[3] | m1==x[4])) 

예를 들어, 가정 :

m1 

    [,1] [,2] [,3] 
[1,] 3 6 4 
[2,] 9 8 11 
[3,] 10 1 12 
[4,] 2 5 7 

m2 

    [,1] [,2] 
[1,] 3 6 
[2,] 2 7 
[3,] 1 5 
[4,] 8 4 

을 그리고, 그것은 당신에게 줄 것이다 :

 [,1] [,2] 
[1,] 2 0 
[2,] 2 2 
[3,] 0 2 

업데이트 시간의 효율성에 대한 먹은

영업 이익이 코멘트에 언급 한 것처럼 그래서

  • 순진 for 솔루션에 대한 20 mins
  • 내 솔루션은 @alexis_laz 약 36 secs
  • 그 소요됩니다, 요약하기 약 12 secs

동일한 작업을 수행하는 경우.

+1

Thanks @ 989! 또한 36 초 내에 솔루션을 통해 내 데이터 세트에서 솔루션을 시도했습니다. 고맙습니다! – Andres

+1

@Andres 알아두면 좋을 것. 그래서 순진한'for' 솔루션보다 훨씬 빠릅니다. 득표에 의한 해결책에 감사하는 것이 더 낫다;) – 989

+1

미안하다 @ 989, 나쁘다! 투표를 잊어 버렸습니다 :) – Andres