2014-03-26 7 views
0

나는 다음과 같은 SAS 데이터 세트가 있습니다분할 한 관찰

data mydata; 
    LENGTH id 4.0 num 4.0 A $ 4. B $ 8. C $ 20.; 
    input id num A $ B $ C $; 
    datalines; 
1 1 x yy zzzzz 
2 1 x yy zzzzz 
3 2 xq yyqq zzzzzqqqqq 
4 1 x yy zzzzz 
5 3 xqw yyqqww zzzzzqqqqqwwwww 
6 1 x yy zzzzz 
7 4 xqwe yyqqwwee zzzzzqqqqqwwwwweeeee 
; 

문제가

mydata 
------------------- 
id num A B C 
1 1 x yy zzzzz 
2 1 x yy zzzzz 
3 2 xq yyqq zzzzzqqqqq 
4 1 x yy zzzzz 
5 3 xqw yyqqww zzzzzqqqqqwwwww 
6 1 x yy zzzzz 
7 4 xqwe yyqqwwee zzzzzqqqqqwwwwweeeee 

처럼 보이는 납입이> (1) 실제로 데이터를 포함 관측 각 다수의 "관찰"과 나는 SAS의 일부 논리를 사용하여 그것을 나누고 싶다. 여기에 내가 얻을 원하는에 대한 예는 다음과 같습니다

mydatawanted 
------------------- 
id num A B C 
1 1 x yy zzzzz 
2 1 x yy zzzzz 
3 1 x yy zzzzz 
3 1 q qq qqqqq 
4 1 x yy zzzzz 
5 1 x yy zzzzz 
5 1 q qq qqqqq 
5 1 w ww wwwww 
6 1 x yy zzzzz 
7 1 x yy zzzzz 
7 1 q qq qqqqq 
7 1 w ww wwwww 
7 1 e ee eeeee 

기본적으로, NUM> (1) I 출력 후 납입 새로운 관찰과 같은 사람들을, 그 길이에 따라 각 변수의 문자열을 각 항목에 대해하고 싶은 경우 = 여기에 1. 내가 지금까지 코드에 시도 것입니다 :

data mydata2(drop=i _:); 
    set mydata; /*use the data from the original data set */ 
    _temp_id = id; /*create temp variables from the currently read observation */ 
    _temp_num = num; 
    _temp_A = A; 
    _temp_B = B; 
    _temp_C = C; 
    if (_temp_num > 1) THEN /* if num in current record > 1 then split them up */ 
     do i = 1 to _temp_num; 
      id = _temp_id; /* keep id the same */ 
      num = 1; /* set num to 1 for each new observation */ 
      A = substr(_temp_A,i,i); /*split the string by 1s */ 
      B = substr(_temp_B,1 + 2 * (i - 1),i * 2); /*split the string by 2s */ 
      C = substr(_temp_C,1 + 5 * (i - 1),i * 5); /*split the string by 5s */ 
      OUTPUT; /* output this new observation with the changes */ 
     end; 
    else OUTPUT; /* if num == 1 then output without any changes */ 
run; 

그러나 나는 그것을 원하는대로 (I 각 단계에서 무슨 일이 일어 났는지 생각 보여 일부 의견에 넣어) 작동하지 않습니다. 실제로 다음 결과가 생성됩니다.

mydata2 
------------------- 
id num A B C 
1 1 x yy zzzzz 
2 1 x yy zzzzz 
3 1 x yy zzzzz 
3 1 q qq qqqqq 
4 1 x yy zzzzz 
5 1 x yy zzzzz 
5 1 qw qqww qqqqqwwwww 
5 1 w ww wwwww 
6 1 x yy zzzzz 
7 1 x yy zzzzz 
7 1 qw qqww qqqqqwwwww 
7 1 we wwee wwwwweeeee 
7 1 e ee eeeee 

이 mydata2 결과는 mydatawanted와 같지 않습니다. num = 1 인 행은 괜찮지 만 num> 1 일 때 출력 레코드는 내가 원하는 것과 많이 다릅니다. 총 레코드 수는 정확합니다. 어떤 일이 일어나고 있는지 잘 모르겠다. 이처럼 복잡한 SAS 로직을 처음 시도한 것이므로, 코드를 수정하거나 다른 방법으로 원하는 것을 성취하는데 도움이된다. 고맙습니다!

편집 : 원래 입력 된 mydata 데이터 문에 문제가 있으며 질문이 업데이트되었습니다.

+1

첫 번째 얇은 작업은이 데이터를 제공 한 사람에게 돌아가서 대화를 나누는 것입니다. 이것은 데이터를 저장하는 끔찍한 방법입니다. – Joe

+0

하하, 나는 동의한다! 나는 그들이 우주를 어떻게 든 구하려고 노력했다고 믿는다. –

답변

1

부분 문자열이 잘못되었습니다. Substr은 (original string, start, ending position)이 아니라 (original string, start, length) 인수를 취합니다. 따라서 length1,2,5이 아니고 i,i*2,i*5이되어야합니다.

 A = substr(_temp_A,i,1); /*split the string by 1s */ 
     B = substr(_temp_B,1 + 2 * (i - 1),2); /*split the string by 2s */ 
     C = substr(_temp_C,1 + 5 * (i - 1),5); /*split the string by 5s */ 
+1

나는'if' 코드를 제거하고 간단히 _every_ 행을 위해 코드를 작성하는 것을 권장합니다. i = 1이면 아무 것도하지 않지만 코드 블록은 정확히 오래 걸리지 않습니다. 수천만 개의 레코드를 파싱하지 않는 한, 추가 시간은 중요하지 않지만 코드 단순성으로 인해이를 유지하기가 더 쉽습니다. – Joe

+0

D' oh, 한편으로는 실수로 유감 스럽지만, 다른 한편으로는 너무 복잡해서 정말 기쁩니다. 이것은 그것을 완벽하게 고쳤다. 그런데, 좋은 점은 if, 실제로 많은 레코드를 처리하고 있습니다. (수천 만, 어쩌면 약 1 백만 정도입니까?)하지만 당신이 맞을 경우 아마 속도에 많은 영향을 미치지 않을 것입니다. 또한 Joe의 도움에 다시 한 번 감사드립니다! –