본문 바로가기
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

     

    반응형

    댓글