Похоже, вы хотите использовать данные формата в TEST2 для преобразования значений в TEST1 в коды.Итак, для CITY у вас есть три уровня, поэтому вы хотите сгенерировать значения 1,2,3.Таким образом, вы можете сделать это с форматами, но если вы хотите, чтобы результаты были числами, а не строками, вам нужно использовать вызов функции INPUT () для преобразования отформатированного значения обратно в число.
Сначала давайтеСоздайте пример данных, используя обычный код SAS, поскольку редактировать тестовые данные гораздо проще, чем редактировать операторы SQL INSERT.
data test1;
input id $ city country ;
cards;
1639 5 42260
1065 10 38090
1400 15 29769
;
data test2;
input condition $ g_l $ g_p $ ;
cards;
city low 6
city 7 16
city 17 high
country low 1000
country 1001 high
;
Мы можем преобразовать набор данных TEST2
в формат.Мы можем использовать шаг данных для создания данных, необходимых для определения форматов с помощью PROC FORMAT.Давайте предположим, что он уже отсортирован по условию по категориям, которые вы хотите создать, чтобы мы могли генерировать номера категорий.Также я предполагаю, что CONDITION является допустимым именем формата (начинается с буквы или подчеркивания и НЕ заканчивается цифрой).
data formats ;
length fmtname $32 start end 8 hlo $3 label $32 ;
keep fmtname -- label;
set test2;
by condition notsorted;
if first.condition then row=1;
else row + 1;
fmtname = condition ;
start=input(g_l,??32.);
end=input(g_p,??32.);
if g_l='low' then hlo=cats(hlo,'L');
if g_p='high' then hlo=cats(hlo,'H');
label = left(put(row,32.));
run;
proc format cntlin=formats ;
run;
Чтобы использовать эти форматы для преобразования значений в номера категорий, которые мы должны сгенерироватьнекоторый код.Когда список переменных достаточно мал, вы можете поместить код в одну макропеременную (максимальная длина 64 Кбайт).
Например, если мы хотим сгенерировать новые переменные с суффиксом _GRP
для любой переменной во входном наборе данных, TEST1
, имя которой находится в списке условий в таблице метаданных, TEST2
.Мы могли бы использовать такой код для генерации макропеременной.
proc contents data=test1 out=contents noprint;
run;
proc sql noprint ;
select distinct cats(name,'_grp=input(put(',name,',',name,'.),32.)')
into :recode separated by ';'
from contents
where upcase(name) in (select upcase(condition) from test2)
;
quit ;
Для вашего примера макропеременная RECODE
выглядит следующим образом:
city_grp=input(put(city,city.),32.);
country_grp=input(put(country,country.),32.)
, которую затем можно использовать вшаг даты для создания нового набора данных из вашего старого.
data want ;
set test1 ;
&recode;
run;
Результаты:
country_
Obs id city country city_grp grp
1 1639 5 42260 1 2
2 1065 10 38090 2 2
3 1400 15 29769 2 2
Если у вас много переменных, которые вы кодируете, вместо генерации макропеременнойвместо этого вы можете просто написать код в файл.
proc sql noprint ;
create table names as
select distinct name
from contents
where upcase(name) in (select upcase(condition) from test2)
;
quit ;
filename code temp;
data _null_;
set names ;
file code ;
put name +(-1) '_grp=input(put(' name ',' name +(-1) '.),32.);' ;
run;
data want ;
set test1 ;
%include code / source2;
run;
Возможно, вы также захотите сгенерировать еще одну серию форматов, которые вы могли бы использовать для декодирования категорий обратно в описания.Поэтому для вашей новой переменной CITY_GRP
вы можете сгенерировать формат CITY_GRP.
, который будет переводить 1
в low - 6
и т. Д.
data format2 ;
length fmtname $32 start 8 label $50 ;
keep fmtname -- label;
set test2;
by condition notsorted;
if first.condition then row=1;
else row + 1;
fmtname = catx('_',condition,'grp') ;
start=row ;
label = catx(' - ',g_l,g_p);
run;
proc format cntlin=format2; run;
proc print data=want;
format city_grp city_grp. country_grp country_grp.;
run;
Результат:
Obs id city country city_grp country_grp
1 1639 5 42260 low - 6 1001 - high
2 1065 10 38090 7 - 16 1001 - high
3 1400 15 29769 7 - 16 1001 - high