как создать переменные, имена которых совпадают с двумя именами переменных массива - PullRequest
1 голос
/ 15 марта 2020

У меня есть набор данных H CC DATA_H CC, который с идентификатором члена и 79 двоичными переменными:

Member_ID   HCC1    HCC2    HCC6    HCC8 ...    HCC189
XXXXXXX1    1       0       1       0    ...    0
XXXXXXX2    0       0       1       0    ...    0
XXXXXXX3    0       1       0       0    ...    1

Я пытаюсь создать выходной набор данных, который может создать новые двоичные переменные для всех Сочетание этих 79 переменных. Каждая новая переменная представляет, если член имел обе переменные как 1.

%LET hccList =  HCC1 HCC2 HCC6 HCC8 HCC9 HCC10 HCC11 HCC12 HCC17 HCC18 HCC19 HCC21 HCC22 HCC23 HCC27 
                HCC28 HCC29 HCC33 HCC34 HCC35 HCC39 HCC40 HCC46 HCC47 HCC48 HCC54 HCC55 HCC57 HCC58 
                HCC70 HCC71 HCC72 HCC73 HCC74 HCC75 HCC76 HCC77 HCC78 HCC79 HCC80 HCC82 HCC83 HCC84 
                HCC85 HCC86 HCC87 HCC88 HCC96 HCC99 HCC100 HCC103 HCC104 HCC106 HCC107 HCC108 HCC110 
                HCC111 HCC112 HCC114 HCC115 HCC122 HCC124 HCC134 HCC135 HCC136 HCC137 HCC157 HCC158 
                HCC161 HCC162 HCC166 HCC167 HCC169 HCC170 HCC173 HCC176 HCC186 HCC188 HCC189;

DATA COUNT_HCC; SET DATA_HCC;
    ARRAY HCC [*] &hccList.;
    DO i = 1 TO DIM(HCC);
        DO j = i+1 TO DIM(HCC);
            %LET HCC_COMBO = CATX('_', VARNAME(HCC[i]), VARNAME(HCC[j]));
            &HCC_COMBO. = MIN(HCC[i], HCC[j]);
        END;
    END;
RUN;

Я пытался использовать функцию CATX, чтобы просто объединить имена двух переменных, но это не сработало.

Вот ошибка журнала, которую я получил:

ERROR: Undeclared array referenced: CATX.
ERROR: Variable CATX has not been declared as an array.
ERROR 71-185: The VARNAME function call does not have enough arguments.

И пример вывода результатов будет выглядеть так:

Member_ID   HCC1_HCC2    HCC1_HCC6    HCC1_HCC8   ...    HCC188_HCC189
XXXXXXX1    0               1           0         ...       0
XXXXXXX2    0               0           0         ...       0
XXXXXXX3    0               0           0         ...       1

Ответы [ 3 ]

2 голосов
/ 15 марта 2020

Для создания динамического c генерирования имени переменной используйте макрос для создания необходимых вам переменных. Приведенный ниже код генерирует динамические c имена переменных и генерирует код шага данных для создания переменных.

%macro get_hcc_combo_mins;
    %do i = 1 %to %sysfunc(countw(&hccList.));
        %do j = %eval(&i.+1) %to %sysfunc(countw(&hccList.));
            %let hcc1 = %scan(&hccList., &i.);
            %let hcc2 = %scan(&hccList., &j.);

            &hcc1._&hcc2. = min(&hcc1., &hcc2.);
        %end;
    %end;
%mend;

DATA COUNT_HCC; SET DATA_HCC;
    ARRAY HCC [*] &hccList.;
    %get_hcc_combo_mins;
RUN;

Макрос %get_hcc_combo_mins генерирует этот код на шаге данных:

HCC1_HCC2 = min(HCC1, HCC2);
HCC1_HCC6 = min(HCC1, HCC6);
HCC1_HCC8 = min(HCC1, HCC8);
...

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

1 голос
/ 16 марта 2020

Шаг DATA с LEXCOMB может генерировать пары имен переменных. CALL EXECUTE отправить заявление, используя эти имена.

Пример:

Предполагается HCC: имена переменных, которые указывают c имена, не известные априори.

data have;
  call streaminit(1234);
  do id = 1 to 100;
    array hcc hcc1 hcc3 hcc5 hcc7 hcc10-hcc79 hcc150 hcc155 hcc180 hcc190-hcc191;
    do over hcc; 
      hcc = rand('uniform', dim(hcc)) < _i_;
    end;
    output;
  end;
run;

data _null_;
  set have;
  array hcc hcc:;

  do _n_ = 1 to dim(hcc);
    hcc(_n_) = _n_;
  end;

  call execute("data pairwise; set have;");

  do _n_ = 1 to comb(dim(hcc),2);
    call lexcomb(_n_, 2, of hcc(*));

    index1 = hcc(1);
    index2 = hcc(2);

    name1 = vname(hcc(index1));
    name2 = vname(hcc(index2));

    put name1=;

    call execute (cats(
      catx(    '_',name1,name2),
      '=',
      catx(' and ',name1,name2),
      ';'
    ));
  end;

  call execute('run;');

  stop;
run;
0 голосов
/ 15 марта 2020

Посмотрите, можете ли вы использовать это как шаблон.

/* Example data */
data have (drop = i j);
   array h {*} HCC1 HCC2 HCC6 HCC8 HCC9 HCC10 HCC11 HCC12 HCC17 HCC18 HCC19 HCC21 HCC22 HCC23 HCC27 
               HCC28 HCC29 HCC33 HCC34 HCC35 HCC39 HCC40 HCC46 HCC47 HCC48 HCC54 HCC55 HCC57 HCC58 
               HCC70 HCC71 HCC72 HCC73 HCC74 HCC75 HCC76 HCC77 HCC78 HCC79 HCC80 HCC82 HCC83 HCC84 
               HCC85 HCC86 HCC87 HCC88 HCC96 HCC99 HCC100 HCC103 HCC104 HCC106 HCC107 HCC108 HCC110 
               HCC111 HCC112 HCC114 HCC115 HCC122 HCC124 HCC134 HCC135 HCC136 HCC137 HCC157 HCC158 
               HCC161 HCC162 HCC166 HCC167 HCC169 HCC170 HCC173 HCC176 HCC186 HCC188 HCC189;

   do i = 1 to 10;
      do j = 1 to dim (h);
         h [j] = rand('uniform') > .5;
      end;
      output;
   end;
run;

/* Create long version of output data */
data temp (drop = i j);
   set have;
   array a {*} HC:;
   do i = 1 to dim (a)-1;
      do j = i+1 to dim (a);
         v = catx('_',  vname (a[i]), vname (a[j]));
         d = a [i] * a [j];
         n = _N_;
         output;
      end;
   end;
run;

/* Transpose to wide format */
proc transpose data=temp out=temp2 (drop=_: n);
    by n;
    id v;
    var d;
run;

/* Merge back with original data */
data want;
   merge have temp2;
run;
...