본문 바로가기
SAS/SAS Tip's

[IML] 관측치 행단위 기준으로 최빈값(Mode) 구하기

by 기서무나구물 2022. 10. 5.

* Mode 함수를 제공하지 않는 관계로 일반적으로는 배열, Hash Object, 전치 후 통계 프로시져 등의 방법으로 최빈값을 구할 수 있고, 아래는 Proc iml의 freq함수와 level함수를 사용하여서 행 단위의 최빈값 계산하여 원 데이터에 결합하는 방식으로 구현.

 

* 질문 : https://cafe.daum.net/statsas/B3m/15467

 

* [엑셀과 SAS함수] MODE 함수 : https://statwith.tistory.com/2433

 

 

data have;
infile cards expandtabs;
input Chrom Pos ID1 ID2 ID3 ID4 ID5 ID6 ID7 ID8;
cards;
1 8456  0 0 0 0 0 . 1 1
1 9948  0 0 2 . 1 2 2 2
1 10058 1 1 1 1 1 1 . 1
2 6535  0 . 0 0 0 0 1 1
2 8967  1 1 0 1 1 1 0 .
2 10234 1 1 1 0 0 1 1 1
3 1023  0 0 1 2 0 0 0 0
3 9978  1 2 0 . 2 2 2 2
3 15032 0 0 0 1 1 2 1 1
;
run;

테이블 처리 방식

SAS Programming
proc iml;
     CREATE Temp_table VAR{ ROW_MODE};
     use have(keep=ID:);

     read all var _all_ into x[c=vname];
     close;

     do i=1 to nrow(x);
        row=x[i,];
        call tabulate(level,freq,row);
        ROW_MODE=level[freq[<:>]];
        APPEND;

     end;
     close Temp_table;
     
     * 일단 Temp_table 생성 후 처리;
     Temp_table = TableCreateFromDataSet("work", "Temp_table");
     row_mode   = TableGetVarData(Temp_table, "ROW_MODE");     
     
     
     * have 테이블을 행렬로 생성;
     have_table = TableCreateFromDataSet("work", "have");
     
     * 행렬에 변수 추가;
     call TableAddVar(have_table, "row_mode", row_mode);

     * 테이블을 SAS 테이블로 변경;
     call TableWriteToDataSet(have_table, "work", "mode_table");

quit;

 

Results
OBS    Chrom     Pos     ID1    ID2    ID3    ID4    ID5    ID6    ID7    ID8    row_mode

 1       1       8456     0      0      0      0      0      .      1      1         0   
 2       1       9948     0      0      2      .      1      2      2      2         2   
 3       1      10058     1      1      1      1      1      1      .      1         1   
 4       2       6535     0      .      0      0      0      0      1      1         0   
 5       2       8967     1      1      0      1      1      1      0      .         1   
 6       2      10234     1      1      1      0      0      1      1      1         1   
 7       3       1023     0      0      1      2      0      0      0      0         0   
 8       3       9978     1      2      0      .      2      2      2      2         2   
 9       3      15032     0      0      0      1      1      2      1      1         1

Merge 함수로 빈도값 추가하기

 

SAS Programming
proc iml;
     CREATE Temp_table VAR{ ROW_MODE};
     use have(keep=ID:);
     read all var _all_ into x[c=vname];
     close;

     do i=1 to nrow(x);
        row=x[i,];
        call tabulate(level,freq,row);
        ROW_MODE=level[freq[<:>]];
        APPEND;
     end;
quit; 

data new_table;
 merge have Temp_table;
run;

 

Results
OBS    Chrom     Pos     ID1    ID2    ID3    ID4    ID5    ID6    ID7    ID8    ROW_MODE

 1       1       8456     0      0      0      0      0      .      1      1         0   
 2       1       9948     0      0      2      .      1      2      2      2         2   
 3       1      10058     1      1      1      1      1      1      .      1         1   
 4       2       6535     0      .      0      0      0      0      1      1         0   
 5       2       8967     1      1      0      1      1      1      0      .         1   
 6       2      10234     1      1      1      0      0      1      1      1         1   
 7       3       1023     0      0      1      2      0      0      0      0         0   
 8       3       9978     1      2      0      .      2      2      2      2         2   
 9       3      15032     0      0      0      1      1      2      1      1         1

 

반응형

댓글