2014-01-28 4 views
1

다른 모든 고객에게 각 고객의 평균 (유클리드) 거리를 계산 나는 다음과 같은 속성을 가진 60K 고객의 SAS 데이터 세트를
4) 매장 방문
SAS는 : <br/>이 1) 고객 수 <br/> 2) X <br/> 3) Y 좌표 : 테이블

나는 각각의 거리가 방문의 비교 고객의 수에 의해 가중되는 테이블의 다른 모든 고객에게 각 고객의 평균 가중치 거리를 계산해야

좌표. 예를 들어, 고객 A & 고객 B 사이의 거리는 10입니다. 그런 다음 고객 B의 방문수 (2)가 5 인이 거리를 가중시킵니다.이 프로세스는 테이블의 다른 모든 고객에 대해 반복되며 평균 이 모든 60k 고객에 대한 가중 거리.

나는 이것을하기위한 무차별 대입 방식이 데카르트 조인 (즉, 60k x 60k = 36 억 레코드 테이블 만들기)이지만 메모리가 부족하거나 SAS가 중단 될 가능성이 높습니다. 나는 이것을 더 다루기 쉬운 데카르트 조인 (즉, 10 x 60K = 600k x 6000 회 반복으로 분해하는 것을 고려해 보았지만 이것은 꽤 시간이 많이 걸릴 것 같다 - 어쩌면 나의 유일한 선택 일 수도있다). 나는 너희들을 추측하고있다/gals는 이것을하는 훨씬 더 좋은 방법을 안다!

의견을 보내 주시면 감사하겠습니다.

도움 주셔서 감사합니다.

+0

이 디자인 문제 같은 소리를 올 수로 : 이유 이 방법으로 설계된 프로젝트입니까? 아마도 이런 종류의 계산을 필요로하지 않는 더 나은 디자인을 고려해보십시오. 클러스터 분석을하고 있다면 SAS 프로 시저를 사용해보십시오. – Joe

+0

@ Joe, 나는 이것이 일부 클러스터 분석 인 경우 덜 집중적 인 절차를 사용하여 절차에서 더 잘 수행 될 것이라고 동의합니다. 그러나, 모든 점 사이에서 이와 같은 연계를 계산한다는 것을 알고있는 절차는 없습니다. 저자가 그룹의 유사성을 나타 내기 위해 숫자를 찾고 있다면 평균으로부터의 가중 평균 거리가 더 나은 선택 일 수 있으며 계산하기가 훨씬 쉽습니다. – DomPazz

+0

@Joe, 프로젝트는 상점 주변의 고객 유치원을 계산하는 것입니다. 우리는 지리적으로 위치한 60k 고객을 보유하고 있으며 52 주 방문 행동을 계산했습니다. 아이디어는 각 고객에 대해 주변 고객의 유형을 설명하는 점수를 작성하는 것입니다. 여기서 주요 아이디어는 고객 A가 상점을 자주 방문하는 다른 고객과 가까운 곳에 거주하면 고객 A가 상점의 집수 영역에 살 가능성이 높다는 것입니다. 반대로, 고객 Z가 간신히 상점을 방문하는 다른 고객과 가까운 곳에 살면 그 고객은 저수지에 살지 않을 가능성이 높습니다. –

답변

2

나쁜 소식은이 계산 속도를 향상시킬 방법이 없다는 것입니다.

카티 전 곱 (Cartesian product)을 수행하면 SAS가 충돌하지 않거나 메모리 부족 현상이 발생하지 않습니다. 다른 좋은 소식은 데이터 단계에서 이렇게하는 것이 PROC SQL에서 수행하는 것보다 빠르다는 것입니다.

data test; 
do cn=1 to 64000; 
    x = ceil(Ranuni(13)*100); 
    y = ceil(ranuni(13)*100); 
    visits = max(1,round(rannor(12)*3 + 8,1)); 
    output; 
end; 
run; 

sasfile test load; 

data ave_dist(keep=cn ave_dist); 
set test end=last; 

dist=0; 
td= 0; 
total_visits=0; 
do i=1 to n; 
    set test(rename=(cn=cn_2 x=x_2 y=y_2) drop=visits) point=i nobs=n; 

    if cn ^= cn_2 then do; 
     xx = (x-x_2); 
     yy = (y-y_2); 
     total_visits = total_visits + visits; 
      dist = sqrt(xx*xx + yy*yy); 
     if dist^= 0 then 
      dist = 1/dist; 
    else 
     dist = 100; /*Adjust to something that makes sense to your data*/ 
     td = visits*dist + td; 
    end; 
end; 

ave_dist = td/total_visits; 
output; 

run; 

sasfile test close; 

나는 거리 계산을 거꾸로했다. 작은 거리에서 더 높은 점수를 원합니다. 나는 이것을 진정한 방문 가중 평균으로 만들었다.

내 노트북에서 실행하는 데 약 13 분이 걸립니다.

+0

@DomPass,이 문제를 조사해 주셔서 대단히 감사합니다. Cartesion Join으로 인해 내가 의심하는 심각한 문제가 발생하지 않는다는 사실을 듣는 것이 좋습니다. 위의 코드 (데이터 문 사용)는 모든 고객에 대해 단 하나의 평균을 계산하지만 대신 각 고객의 평균이 필요합니다 (예 : 다른 모든 고객과의 평균 거리). 더 이상, 내가 사용하려고했던 가중치는 작동하지 않을 것입니다. 내가하는 일은 방문 횟수가 많지 않은 고객 옆에 살고 방문 횟수가 적은 고객 옆에 사는 경우 점수를 낮게 책정하는 것입니다. 어떤 아이디어? –

+0

@AdamL,'if last then do' 문 대신에, 평균값과'output;'을 계산하십시오. 나는 당신이 찾고 있다고 생각하는 것을 달성하기 위해 코드와 설명을 업데이트 할 것이다. – DomPazz

+0

@DomPass,이 작품은 훌륭합니다! 후속 조치에 대해 대단히 감사합니다. –

1

고객 기반이 < 100k가 될 경우 PROC DISTANCE이 도움이 될 수 있습니다. @DomPazz에서 만든 데이터 세트를 사용하면 다음 코드를 실행하고 결과를 검사 할 수 있습니다. 이 경우에는 16 초 만에 실행되는 첫 번째 10K 고객 만 시험해 보겠습니다. 그게 속임수로 당신을 거짓된 안보 의식에 빠뜨리지 마라. 너가 두배가되면 고객의 시간은 4 배가됩니다. (실제 시간 : 10K - 16secs, 20K - 47 초, 40K - 3mins ...) (N이고 노 고객의 사용자 입력 데이터 세트.)

이 절차는 NxN 정방 행렬을 생성한다. SAS가 어느 시점에서 RAM 메모리 문제 (적어도 1.10 * NxN * 8 바이트 정도의 하드 드라이브 공간을 확보해야하는지)를 시도하고 실험 해 볼 수 있습니다. 행렬의 각 셀은 '고객'과 '고객'의 열 (행) 거리가 i입니다. 일단 거리를 얻으면 고객의 방문 거리와 평균 거리를 곱하는 간단한 문제입니다.

proc distance data = test(obs = 100) 
OUT=test_distances(compress = binary) 
METHOD= EUCLID shape = SQUARE 
UNDEF=1000000 
VARDEF=wdf; 
var INTERVAL(x y) 
; 
copy cn visits; 
run; 

data avg_dist; 
set train_distances; 
array dist{*} dist:; 
prod=0; 
do i = 1 to dim(dist); 
prod = visits*dist{i}+prod; 
end; 

avg_dist=prod/dim(dist); 

dims=dim(dist); 

drop i dist: 
; 
run; 
proc sql; 
drop table test_distances; 
quit; 

해결하려는 문제의 유형은 일반적으로 k-nearest neighbour 문제로 알려져 있습니다. 이 분야에서 수십 년에 걸친 연구가 있었으며, 대부분이 성능을 위해 Kd-trees과 같은 특별한 데이터 구조를 사용하여 해결되었습니다.대부분의 사람들은 who are the top-10 (or K) closest customers to this customer I'm interested in?과 같은 질문에 대답하는 데 관심이 있습니다. 이러한 유형의 문제를 효율적으로 해결하는 또 다른 절차는 이며 kd-treeRd-tree이라고하는 SAS의 독점 구조를 모두 지원합니다. 그러면 PDF 문서 만 찾을 수 있습니다 from SAS Eminer 4.3 일

N * N 개 항목 사이의 거리를 계산해야하는 순간 문제가 발생합니다. 코멘트에서 프로젝트 설명을 읽는 것만으로는 모든 고객과 모든 고객 사이의 거리를 계산하는 것이 아니라 모든 고객과 모든 상점 간의 거리와 같은 거리를 계산하는 것이 필요합니다.

이렇게하면 문제의 차원이 크게 줄어들어 쿼리 성능이 크게 향상됩니다.

N 개의 고객과 S 점포가 있고 N * S 점 사이의 거리 만 계산하면됩니다. (단순한 데이터 단계는 직교 좌표계 제품이나 특수 데이터 구조가 필요하지 않으므로 작업을 수행합니다.)

거기에서 S의 각 상점에 대해 해당 매장에서 구매 한 고객의 비율을 볼 수 있습니다 1KM에서 2KM는 3KM .... 그런

당신은 라이브 2KM 등 내에서 1km, 15 % 내에서 다음과 같은 80 % 라이브 답변 ...

+0

@ uer102890, 내가 각 고객에게 계산하려는 이유는 집수를 결정하기 위해 그들의 행동이 필요하기 때문입니다. 예, 상점까지의 거리를 쉽게 계산할 수 있습니다. 그러나 그것은 내가 임의적 인 유역 컷오프를 만드는 것임을 의미합니다. 그러나 고객의 주머니가 지난 52 주 중 매주 방문하는 경우이 고객 그룹 (그리고 가까운 고객)이 유역에 있다고 가정 할 수 있습니다. 본질적으로, 나는 고객들이 그들이 저수지에 있다는 것을 보여 주길 바란다. –

관련 문제