Хотите динамически изменять имена переменных в SAS - PullRequest
0 голосов
/ 20 июня 2020

Существует ли управляемый данными способ динамического изменения имен переменных с одного имени на другое, где каждый набор данных может иметь или не иметь исходную переменную? Я хочу перебрать каждый набор данных, чтобы изменить старую переменную (если она существует, поскольку в некоторых наборах данных больше переменных, чем в других) и назначить ее как одно новое стандартное имя переменной. Как это можно сделать на основе данных?

Должно быть:

%let statement
array with do loop
Read in excel file with variable lists and rename statement old=new
macro

Например,

Набор данных 1

ProvID NPI Txnmy_cd Txnmy_cd2 Spec_cd1 Spec_cd2 Spec_cd3 Spec_cd4

Набор данных 2

ProvID NPI Txnmy_cd1 Txnmy_cd2 Txnmy_cd3 Txnmy_cd4 Spec_cd Spec_cd1

Набор данных 3

ProvID NPI Txnmy_cd Txnmy_cd2 Txnmy_cd3 Txnmy_cd4 Spec_cd1 Spec_cd2

и так далее ...

Окончательный результат:

Набор данных 1

ProvID NPI Taxonomy Taxonomy2 Taxonomy3 ProvSpec1 ProvSpec2 ProvSpec3 ProvSpec4

Набор данных 2

ProvID NPI Taxonomy Taxonomy2 Taxonomy3 Taxonomy4 ProvSpec1 ProvSpec2 

Набор данных 3

ProvID NPI Taxonomy Taxonomy2 Taxonomy3 Taxonomy4 ProvSpec1 ProvSpec2

и так далее ...

1 Ответ

1 голос
/ 20 июня 2020

Наиболее детерминированный c способ - поддерживать таблицу сопоставления преобразований имен.

Пример (сопоставление основано на конечном результате, показанном в вопросе)

xl_name   sas_name        based on
-------   --------        -----------
Txnmy_cd  Taxonomy        per 1 2 3
Txnmy_cd1 Taxonomy        per   2
Txnmy_cd2 Taxonomy2       per 1 2 3
Txnmy_cd3 Taxonomy3       per   2 3
Txnmy_cd4 Taxonomy4       per   2 3
Spec_cd   ProvSpec1       per   2
Spec_cd1  ProvSpec1       per 1   3
Spec_cd1  ProvSpec2       per   2     # inconsistent
Spec_cd2  ProvSpec2       per 1   3
Spec_cd3  ProvSpec3       per 1
Spec_cd4  ProvSpec4       per 1

Сначала результат примеры для sas_name целевых объектов несовместимы

  • для таксономии первое переименование - Taxonomy
  • для Provspe c первое переименование - ProcSpec1

Во-вторых, реальный мир вторгается в исходную таблицу сопоставления

  • преобразование данных 2 окончательного результата из spec_cd1 в ProvSpec2 не согласуется с другими сопоставлениями, показанными для данных 1 и данные 3.

Реальный вопрос?

Q: Должны ли переименования основываться на префиксах имен переменных, а суффикс 1,2,3,4 на основе порядка появления (количества повторений) суффикса?

Предположим, что это так. Используйте таблицу (или формат) сопоставления префиксов, чтобы найти исходные переменные, которые необходимо переименовать с суффиксом in order numeri c.

Пример:

proc format;
  value $prefix_map
  'Txnmy_cd' = ':Taxonomy'    /* : means 1st does not get 1 suffix */
  'Spec_cd'  = '#ProvSpec'    /* # means 1st does     get 1 suffix */
  other = ' '
  ;

%macro rename_per_prefix(data=);
  %local renames lib mem;

  %let syslast = &data;
  %let lib = %scan(&syslast,1,.);
  %let mem = %scan(&syslast,2,.);

  proc contents noprint data=&data out=_names_(keep=name varnum);
  data _names_;
    set _names_;

    length sas_prefix $25;
    do len = length(name) to 1 by -1 until(not missing(sas_prefix));
      sas_prefix = put(substr(name,1,len),$prefix_map.);
    end;

    if not missing(sas_prefix);
  proc sort 
    data=_names_; by sas_prefix varnum;
  data _null_;
    length renames $32767; retain renames;
    do until (no_more_candidates);
      do index = 1 by 1 until (last.sas_prefix);
        set _names_ end=no_more_candidates;
        by sas_prefix;

        if sas_prefix =: ':' then
          if index = 1 then suffix = ''; else suffix = cats(index);
        else
        if sas_prefix =: '#' then 
          suffix = cats(index);

        newname = cats(substr(sas_prefix,2),suffix);

        renames = catx(' ', renames, catx('=', name, newname));        
      end;
    end;

    call symput('renames', strip(renames));
  run;    

  %if %length(%superq(renames)) %then %do;
  proc datasets nolist lib=&lib;
    modify &mem;
    rename %superq(renames);
  %end;

  proc delete data=_names_;
  run;
%mend;

* mimic data import;
data one;
call missing(ProvID,NPI,Txnmy_cd,Txnmy_cd2,Spec_cd1,Spec_cd2,Spec_cd3,Spec_cd4);
data two;
call missing(ProvID,NPI,Txnmy_cd1,Txnmy_cd2,Txnmy_cd3,Txnmy_cd4,Spec_cd,Spec_cd1);
data three;
call missing(ProvID,NPI,Txnmy_cd,Txnmy_cd2,Txnmy_cd3,Txnmy_cd4,Spec_cd1,Spec_cd2);
run;

* perform renames;

%rename_per_prefix(data=one)
%rename_per_prefix(data=two)
%rename_per_prefix(data=three)

What if

Предположим, что во всех источниках Excel были согласованные преобразования.

После импорта данных набора данных из Excel вы можете использовать Proc CONTENTS и таблицу сопоставления для программного создания SAS код, который выполняет преобразование переименований.

Таблица сопоставления и генерация кода становятся более сложными, если вы разрешаете процессу импорта вводить имена переменных, которые требуют указания литералов имен. (Т.е. импорт приносит переменную с именем 'Provided Specimen #1'n

Пример:

data name_map;
length xl_name sas_name $32;
input 
xl_name  sas_name; datalines;
Txnmy_cd  Taxonomy
Txnmy_cd1 Taxonomy
Txnmy_cd2 Taxonomy2
Txnmy_cd3 Taxonomy3
Txnmy_cd4 Taxonomy4
Spec_cd   ProvSpec1
Spec_cd1  ProvSpec1
Spec_cd2  ProvSpec2 
Spec_cd3  ProvSpec3
Spec_cd4  ProvSpec4
;

%macro rename_per_map(data=, map=name_map);
  %local renames lib mem;

  %let syslast = &data;
  %let lib = %scan(&syslast,1,.);
  %let mem = %scan(&syslast,2,.);

  proc contents noprint data=&data out=_names_(keep=name);
  proc sql noprint;
    select catx('=',xl_name,sas_name) 
    into :renames separated by ' '
    from _names_ source
    join &map    map
      on source.name = map.xl_name
    ;
  %if %length(%superq(renames)) %then %do;
  proc datasets nolist lib=&lib;
    modify &mem;
    rename %superq(renames);
  %end;
  proc delete data=_names_;
  run;
%mend;

* mimic data import;
data one;
call missing(ProvID,NPI,Txnmy_cd,Txnmy_cd2,Spec_cd1,Spec_cd2,Spec_cd3,Spec_cd4);
data two; /* tweaked to be consistent */
call missing(ProvID,NPI,Txnmy_cd1,Txnmy_cd2,Txnmy_cd3,Txnmy_cd4,Spec_cd,Spec_cd2);
data three;
call missing(ProvID,NPI,Txnmy_cd,Txnmy_cd2,Txnmy_cd3,Txnmy_cd4,Spec_cd1,Spec_cd2);
run;

* perform renames;

%rename_per_map(data=one)
%rename_per_map(data=two)
%rename_per_map(data=three)
...