BookmarkSubscribeRSS Feed

[SAS 고수의 팁] 효율적인 SAS Coding

Started ‎02-21-2022 by
Modified ‎02-21-2022 by
Views 3,361

 

 

코딩의 효율성은 일반적으로 CPU 시간, 디스크 공간 또는 메모리 사용량으로 측정됩니다. SAS 프로그램은 많은 양의 데이터를 처리하는 데 사용될 가능성은 낮지만 유사한 처리가 필요한 일련의 시험에서 사용할 수 있도록 업데이트되고 조정될 가능성이 매우 높습니다. 프로그램이 5분 동안만 실행될 때 CPU 시간을 50% 절약해도 코딩 효율성에 큰 영향을 미치지 않습니다. 이번 게시글에서는 다양한 유형의 SAS 프로그램에서 효율적으로 코딩할 때 선택해야 하는 사항에 대해 설명합니다.

1. Speed and Low Maintenance

IF...THEN...ELSE 및 SELECT...WHEN 구문은 속도와 유지 관리 시간을 모두 향상시키기 위해 작성할 수 있는 구문입니다. 3가지의 방법으로 속도와 유지 관리 시간을 향상 시키는 문법을 알아보려 합니다.

아래의 3가지 예시는 A, B, C를 포함하는 입력 데이터 세트의 값을 새 변수로 값을 할당하는 여러 가지 방법입니다.

 

예시 1)

 

DATA new;
SET old;
IF oldvar = 'A' THEN newvar = 1;
IF oldvar = 'B' THEN newvar = 2;
IF oldvar = 'C' THEN newvar = 3;
RUN;

 

첫 번째 예시는 그다지 효율적인 코드는 아닙니다. 이유는 모든 IF 조건이 모든 레코드에 적용되기 때문입니다. 하지만, 작은 데이터셋에 위와 같은 코드를 적용할 경우 비효율적인지 인지하지 못할 수도 있습니다.

 

예시 2)

 

DATA new;
SET old;
IF oldvar = 'A' THEN newvar = 1;
ELSE IF oldvar = 'B' THEN newvar = 2;
ELSE IF oldvar = 'C' THEN newvar = 3;
RUN;

 

다음 코드는 IF 조건이 일치하는 조건까지만 적용되므로 더 효율적입니다. 하지만 이것도 작은 데이터셋에 적용할 경우 효율적인지 비효율적인지 인지하지 못할 수도 있습니다 . IF 조건을 정렬하여 가장 일반적으로 사용되는 값이 맨 위에 배치되도록 하면 속도를 더욱 향상시킬 수 있지만, 데이터가 이미 잘 알려져 있고 가장 일반적인 값이 매우 일반적인 경우가 아니라면 이 값은 유용하지 않을 수 있습니다.

 

예시 3)

 

DATA new;
SET old;
SELECT (oldvar);
WHEN ('A') newvar = 1;
WHEN ('B') newvar = 2;
WHEN ('C') newvar = 3;
OTHERWISE;
END;
RUN;

 

 

IF 조건을 정렬하여 가장 일반적으로 사용되는 값이 맨 위에 배치되도록 하면 속도를 더욱 향상시킬 수 있지만, 데이터가 이미 잘 알려져 있고 가장 일반적인 값이 매우 일반적인 경우가 아니라면 이 값은 유용하지 않을 수 있습니다. 또한, 작은 입력 데이터 세트의 경우 속도가 빨라진 것을 느끼지 못할 수 있습니다.

위와 같은 구문은 동일한 레이아웃을 가지기 때문에 유지 관리가 더 쉽습니다. 따라서 구문 오류가 발생할 위험을 줄이면서 줄을 insert 하거나 delete 할 수 있습니다. 그리고 OTHERWISE 절은 필수 구문으로 이전 조건이 충족되지 않은 경우 기본값을 포함할 수 있는 분명한 위치를 제공합니다.

 

 

2. Speed or Low Maintence - Part1

 

다음 두개의 샘플 코드는 두 변수를 사용하여 세 개의 데이터 세트를 병합한 다음 결과 데이터 세트의 순서를 다른 변수로 변경합니다.

 

 

예시1)

 

PROC SORT DATA = a OUT = a1;
BY cat_b;
RUN;
PROC SORT DATA = b OUT = b1;
BY cat_b;
RUN;
DATA a1_b1;
MERGE a1 (IN = a) b1 (IN = b);
BY cat_b;
IF a AND b;
RUN;
PROC SORT DATA = a1_b1 OUT = a1_b11;
BY cat_c;
RUN;
PROC SORT DATA = c OUT = c1;
BY cat_c;
RUN;
DATA a1_b1_c1;
MERGE a1_b11 (IN = ab) c1 (IN = c);
BY cat_c;
IF ab AND c;
RUN;
PROC SORT DATA = a1_b1_c1;
BY cat_a cat_b cat_c;
RUN;

 

위의 코드는 Proc Sort 와 Data Step이 같이 있는 코드입니다. 코드는 처리에 관한 것은 효율적이지만 병합하기 전에 개별 데이터 세트를 정렬해야 하기 때문에 상당히 길고 복잡합니다.

 

예시2)

 

PROC SQL;
CREATE TABLE a_b_c AS
SELECT a.cat_a
,b.cat_b
,c.cat_c
,a.num_a1
,a.num_a2
,b.num_b1
,b.num_b2
,c.num_c1
,c.num_c2
FROM a
,b
,c
WHERE a.cat_b = b.cat_b
AND a.cat_c = c.cat_c
ORDER BY
a.cat_a
,b.cat_b
,c.cat_c
;
QUIT;

 

위의 예제는 PROC SQL 로 one step 부터 final sort 까지 모두 나와있는 코드입니다. 입력 데이터 세트의 크기가 작거나 중간인 경우 이 코드와 이전 코드에서 사용하는 CPU 시간에는 거의 차이가 없지만 매우 큰 입력 데이터 세트는 PROC SQL을 사용할 때 처리 속도가 느려질 수 있습니다. 단점은 두 개 이상의 데이터 세트를 겹치는 변수로 결합할 때 출력 데이터 세트에 포함될 모든 변수를 나열해야 한다는 것입니다.

장점은 유지보수가 쉽다는 것입니다.

 

 

 

3. Speed or Low Maintenance: Part2

 

단순 병합 코딩은 DATA 또는 PROC SQL 단계를 사용하여 매우 간단하지만 일대일 일치가 아닌 값 범위를 기반으로 테이블을 조인할 때 PROC SQL이 좋은 선택이 될 수 있습니다.

아래의 두개의 예시 코드는 서로 28일 이내의 레코드 간의 가장 큰 차이를 계산합니다.

예시1)

 

 

PROC SORT DATA = old OUT = temp;
BY cat;
RUN;
DATA temp;
SET temp;
BY cat;
RETAIN order;
7
IF FIRST.cat THEN order = 1;
ELSE order + 1;
RUN;
PROC TRANSPOSE DATA = temp OUT = num PREFIX = num;
BY cat;
VAR num;
ID order;
RUN;
PROC TRANSPOSE DATA = temp OUT = val PREFIX = val;
BY cat;
VAR val;
ID order;
RUN;
DATA all (DROP = _:);
MERGE num val;
BY cat;
RUN;
DATA new (KEEP = cat maxval);
SET all;
BY cat;
ARRAY num num:;
ARRAY val val:;
ARRAY test test1-test50;
maxval = .;
reset = 1;
DO i = 1 TO DIM(num);
DO j = i+1 TO DIM(num);
IF num(j) - num(i) LE 28
AND ROUND(val(j) – val(i), .0001) GT maxval
THEN maxval = ROUND(val(j) – val(i), .0001);
END;
END;
IF LAST.cat THEN OUTPUT;
RUN;
​

 

이것은 PROC SORT, PROC TRANSPOSE 및 DATA 단계의 조합으로, 처리에 관한 한 효율적일 수 있지만 모든 개별 레코드 쌍을 범주화하기 위해 배열을 사용해야 하기 때문에 상당히 길고 복잡합니다.

 

 

 

예시2) 

 

PROC SQL;
CREATE TABLE temp AS
SELECT b1.cat
,b1.num
,MAX(b2.val - b1.val) AS maxval
FROM old b1
LEFT JOIN
old b2
ON b1.cat = b2.cat
AND (b2.num - b1.num) BETWEEN 1 AND 28
GROUP BY
b1.cat
,b1.num
;
QUIT;
PROC SQL;
CREATE TABLE new AS
SELECT cat
,MAX(maxval) AS maxval
FROM temp
GROUP BY
cat
;
QUIT;
​

 

이것은 최종 정렬(final sort)을 포함하여 한 단계에서 모든 작업을 수행하는 단일 PROC SQL 단계입니다. 입력 데이터 세트의 크기가 작거나 중간인 경우 이 코드와 이전 코드에서 사용하는 CPU 시간에는 거의 차이가 없지만 매우 큰 입력 데이터 세트는 PROC SQL을 사용할 때 처리 속도가 느려질 수 있습니다.

하지만 이 예제 역시 유지보수하기가 쉽다는 장잠이 있습니다.

 

 

 

Version history
Last update:
‎02-21-2022 06:54 AM
Updated by:
Contributors

sas-innovate-white.png

Register Today!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9.

 

Early bird rate extended! Save $200 when you sign up by March 31.

Register now!

Article Labels
Article Tags