Слева присоединить значение корзины на основе предложения больше, чем - PullRequest
0 голосов
/ 09 июля 2019

Я ищу, чтобы создать оптимальный макрос. Мое первое препятствие - создать эквидистантные ковши. Я использую набор данных sashelp.baseball в качестве примера.

Я беру диапазон логарифмов и делю его на 100, чтобы создать расстояние между каждым ковшом. Затем я хотел бы присвоить столбцу logsalary значение корзины, если logalalary меньше значения корзины

Код, который я пробовал, прилагается. Я надеюсь, что смогу объединить или объединить предельные значения сегмента и использовать условие больше или меньше, чем для добавления значения сегмента

/*Sort the baseball dataset by smallest to largest, removing any missing data*/
PROC SORT
    DATA = sashelp.baseball
        (KEEP = logsalary
         WHERE = (NOT MISSING(logsalary)))
    OUT  = baseball;
    BY logsalary;
RUN;

/*Identify the size of each bucket by splitting the range into 100 equidistant buckets*/
DATA _NULL_;
    RETAIN bin_size;
    SET baseball        END = EOF;

    IF _N_ = 1 THEN DO;
        bin_size = logsalary;
        CALL SYMPUT("min_bin",logsalary);
    END;
    IF EOF      THEN DO;
        bin_size = ((logsalary - bin_size) / 100);
        CALL SYMPUT("bin_size",bin_size);
    END;
RUN;

/*Create a vector to identify each bucket range*/
DATA bin_levels;
    DO bin = 1 TO 100;
        IF bin = 1 THEN DO;
            bin_level = &min_bin.;
            OUTPUT;
        END;
        ELSE DO;
            bin_level = &min_bin. + &bin_size. * bin;
            OUTPUT;
        END;
    END;
RUN;

/*Append a bucket number based on the logsalary being smaller than the next bucket value*/
PROC SQL;
    CREATE TABLE binned_data    AS
    SELECT
          a.*
        , b.bin
        , b.bin_level
    FROM
          baseball              a
    LEFT JOIN
          bin_levels            b   ON b.bin_level > a.logsalary
    ;
QUIT;

Мне бы хотелось, чтобы первые десять строк выглядели так

logSalary     bin
4.2121275979  1
4.2195077052  1
4.248495242   1
4.248495242   1
4.248495242   1
4.248495242   1
4.248495242   1
4.3174881135  2
4.3174881135  2
4.3174881135  2
...

Заранее спасибо

РЕДАКТИРОВАТЬ: сейчас я собираюсь пойти с этим решением

DATA bucketed_data;
    RETAIN bin bin_limit;
    SET baseball;

    IF _n_ = 1 THEN DO;
        bin_limit = logsalary;
        bin = 1;
    END;
    IF logsalary > bin_limit THEN DO;
        bin_limit + &bin_size.;
        bin + 1;
    END; 
RUN;

1 Ответ

1 голос
/ 09 июля 2019

Нет необходимости в макропеременных, поместите значения в набор данных и объедините набор данных с тем, который вы хотите поместить в корзину. Давайте использовать 10 корзин вместо 100, чтобы упростить изучение результатов.

Сначала найдите минимум и диапазон:

proc means n min max data=sashelp.baseball;
 var logsalary;
 output out=stats(keep=min range) min=min range=range;
run;

Затем используйте их для хранения данных:

DATA bucketed_data;
  SET sashelp.baseball (keep=logsalary);
  if _n_=1 then set stats;
  if not missing(logsalary) then do bin=1 to 10 while(logsalary > min+bin*(range/10)); 
     * nothing to do here ;
  end;
run;

Давайте используем PROC MEANS, чтобы посмотреть, как это работает.

proc means n min max ;
 class bin / missing;
 var logsalary;
run;

Результаты:

enter image description here

...