SAS: повысить эффективность перекрестного соединения - PullRequest
2 голосов
/ 19 марта 2019

В моем проекте я объединяю три уникальных источника для получения одного балла. Представьте себе эту формулу

Integrated score = weight_1 * Score_1 + weight_2 * Score_2 + weight_3 * Score_3

Итак, для этого я использовал следующий код

    DATA w_matrix_t;
     /*Create a row count to identify the model weight combination*/
         RETAIN model_combination;
         model_combination = 0;

         DO n_1 = 0 TO 100 BY 1;
               DO n_2 = 0 TO 100 BY 1;
                    IF (100 - n_1 - n_2) ge 0 AND (100 - n_1 - n_2) le 100 THEN DO;
                         n_3 = 100 - n_1 - n_2;
                         model_combination+1;
                         output;
                    END;
               END;
         END;
    RUN;

    DATA w_matrix;
        SET w_matrix_t;
        w_1 = n_1/100;
        w_2 = n_2/100;
        w_3 = n_3/100;
        /*Drop the old variables*/
        DROP n_1 n_2 n_3;
    RUN;

PROC SQL; 
    CREATE TABLE weights_added AS 
    SELECT
          w.model_combination
        , w.w_1
        , w.w_2
        , w.w_3
        , fit.name
        , fit.logsalary
        , (
            w.w_1*fit.crhits    + 
            w.w_2*fit.natbat    + 
            w.w_3*fit.nbb
        )                               AS y_hat_int
    FROM
        work.w_matrix                   AS w
    CROSS JOIN
        sashelp.baseball                AS fit
    ORDER BY
        model_combination;
QUIT;

У меня вопрос: есть ли более эффективный способ сделать это объединение? Цель состоит в том, чтобы создать большую таблицу, содержащую весь набор данных sashelp.baseball, дублированный для всех комбинаций весов.

В моих живых данных у меня есть три входных источника по 46 000 наблюдений каждый, и это перекрестное соединение занимает 1 час. У меня также есть три входных источника по 465 000 каждый, думаю, это займет очень много времени.

Причина, по которой я делаю это таким образом, заключается в том, что я вычисляю D Сомерса, используя частоту Proc и групповую обработку (по комбинации моделей)

1 Ответ

2 голосов
/ 19 марта 2019

5000 копий таблицы с 500 000 строк будет довольно большой таблицей с строками 2.5B

Вот пример стэкирования данных;одна копия have набора данных на строку weights.Пример показывает SET weights для обработки каждого веса (через неявный цикл) и SET have POINT= / OUTPUT внутри явного цикла (внутренний цикл).Внутренний цикл копирует данные , в то время как он вычисляет взвешенную сумму.

data have;
  set sashelp.baseball (obs=200);  * keep it small for demonstration;
run;

data weights (keep=comboId w1 w2 w3);
  do i = 0 to 100; do j = 0 to 100; if (i+j) <= 100 then do;
    comboId + 1;
    w1 = i / 100;
    w2 = j / 100;
    w3 = (100 - i - j) / 100;
    output; 
  end; end; end;
run;


data want (keep=comboid w1-w3 name logsalary y_hat_int);
  do while (not endOfWeights);
    set weights end = endOfWeights;
    do row = 1 to RowsInHave;
      set have (keep=name logsalary crhits natbat nbb) nobs = RowsInHave point = row;
      y_hat_int = w1 * crhits + w2 * natbat + w3 * nbb;
      output;
    end;
  end;
  stop;
run;

proc freq data=want noprint;
  by comboId;
  table y_hat_int / out=freqout ;
  format y_hat_int 4.;
run;

proc contents data=want;
run;

Без манжеты, единственная таблица, содержащая 5 151 копию 200-строчной выдержки из бейсбола, номинально составляет 72,7 МБ,поэтому ожидайте, что 5151 копия таблицы строк размером 465 КБ будет иметь ~ 2,4 ГБ строк и ~ 170 ГБ диска.На диске крутится @ 7200, достигая максимальной производительности на протяжении всего вашего просмотра, в лучшем случае 20 минут только на запись, и, вероятно, намного больше.

...