Я хотел бы разделить свои наблюдения в «родительском» наборе данных на их собственные уникальные «дочерние» наборы данных. Мне нужно сделать это для нескольких родительских наборов данных, поэтому я пытаюсь создать макрос с циклом do внутри для создания этих наборов данных. Но мой код не работает (возможно, по нескольким причинам).
Вот ручной код в качестве примера того, что я хочу автоматизировать (этот код работает нормально, в «родительском» наборе данных ta220092 в этом случае есть четыре наблюдения, а в другом - родительские наборы данных (он может быть больше или меньше):
data ta2200921 ta2200922 ta2200923 ta2200924;
set ta220092;
if _n_ = 1 then output ta2200921;
if _n_ = 2 then output ta2200922;
if _n_ = 3 then output ta2200923;
if _n_ = 4 then output ta2200924;
run;
Пытаясь автоматизировать это. Я подумал, что должен использовать автоматическую переменную «n» для добавления к имени набора данных и для оператора% to, поскольку количество наблюдений в каждом «родительском» наборе данных варьируется, но я не уверен, как это сделать сделай это. Я создал следующий код, в котором есть проблема, с которой, я надеюсь, кто-то может помочь:
%macro treatmentsplit(j);
%do i = 1 %to &j.;
&j. = _n_;
data tatest220092&i.;
set ta220092 (where = (_n_ = &i.));
run;
%end;
%mend treatmentsplit;
%treatmentsplit;
Спасибо.
Помимо редактирования приведенного выше для некоторой ясности, мне нужно отредактировать свой вопрос, чтобы выяснить, почему я не считаю, что это повторяющийся вопрос, как отметил Джо. Предлагаемый им повторяющийся вопрос: Какой самый быстрый как разделить набор данных sas для пакетной обработки?
Я не считаю этот вопрос повторяющимся по двум причинам. Во-первых, основная причина желания разделиться иная. Для моей проблемы это не проблема попытки разбить большой набор данных для разумной пакетной обработки. В следующем абзаце я рассмотрю свою основную причину, по которой я хочу разделиться. Вторая причина, по которой я не считаю это дубликатом, - это код, разрешающий вопрос «Какой самый быстрый способ разбить набор данных SAS для пакетной обработки» не работает в моей ситуации. В двух предоставленных кодовых ответах указывается количество наборов данных, на которые должен быть разделен родительский набор данных. Я не знаю заранее количество разделений для каждого набора данных, который я хочу разделить, поскольку количество наблюдений различается в каждом наборе данных. Я попытался изменить второй ответ (RWill) для моей ситуации, и пока безуспешно. Вот моя лучшая попытка изменить второй ответ на мою ситуацию до сих пор (пробовал варианты):
%macro nobs(dsn);
%local nobs dsid rc;
%let nobs=0;
%let dsid = %sysfunc(open(&dsn));
%if &dsid %then %do;
%let nobs = %sysfunc(attrn(&dsid,NOBS));
%end;
%else %put Open for dataset &dsn failed - %sysfunc(sysmsg());
%let rc = %sysfunc(close(&dsid));
%mend nobs;
%macro batch_process(dsn_in,dsn_out_prefix);
%let dsn_obs = %nobs(&dsn_in);
%let obs_per_dsn = 1;
data
%do i = 1 %to &dsn_obs;
&dsn_out_prefix.&i
%end; ;
set &dsn_in;
drop _count;
retain _count 0;
_count = _count + 1;
%do i = 1 %to &dsn_obs;
if (1 + ((&i - 1) * 1) <= _count <= (&i * 1) then do;
output &dsn_out_prefix.&i;
end;
%end;
run;
%mend batch_process;
%batch_process( dsn_in=tmp1.ta220092 , dsn_out_prefix = ta220092);
Ошибка из журнала, похоже, указывает на то, что существует проблема с переменной DSN_OBS в цикле do (5-я строка во втором макросе):
СИМВОЛГЕН: Макропеременная DSN_OBS разрешается в ОШИБКА: функция% EVAL не имеет выражения для оценки или оператор% IF не имеет условия. ОШИБКА: значение% TO цикла% DO I недопустимо.
Чтобы устранить мою основную причину, по которой я хочу разделить мой набор данных на одно наблюдение на набор данных, я изменил макрос, который почти работает так, как мне нужно, с одной проблемой. Исходный макрос, который я модифицировал, предназначен для сопоставления оценок склонности http://www.biostat.umn.edu/~will/6470stuff/Class25-12/PSmatching.sas. Я модифицирую его, чтобы лучше адресовать свой набор данных (изменяя имена переменных), и я также добавил метод, который я называю «CC» для вычисляемого измерителя, потому что я хочу захватить все элементы управления, которые находятся в пределах 10 или 20% от совпадающей переменной моего лечения group (будет вторая соответствующая переменная, выбранная ближайшим соседом, но у меня нет проблем с кодом для этого шага по строке). Проблема в том, что в наборе данных обработки (например, ta220092 выше) есть два наблюдения, у которых есть совпадающие переменные, которые имеют перекрывающиеся вычисленные «зоны» каверномера: у одного есть активы, которые равны 62, а у другого - 64. Макрос имеет замену вариант; если я выберу «да», то лечение будет сопоставлено с одним и тем же элементом управления 100 раз (не то, что я хочу, я хочу, чтобы все элементы управления были в пределах вычисленного измерителя). Если я выберу «нет» для варианта замены, то макрос будет работать почти так, как я хочу, но контрольные наблюдения, которые потенциально соответствуют двум наблюдениям обработки, которые имеют перекрывающиеся вычисленные измерители, будут разделены между двумя наблюдениями обработки, вместо того, чтобы иметь возможность быть в пределах нормы каждого лечения. Таким образом, макрос не позволяет замену на уровне набора данных, тогда как я хочу, чтобы он не допускал замены на уровне наблюдения. Другими словами, я хочу, чтобы между наблюдениями была замена, но я не уверен, как изменить макрос. Я подумал, что будет проще (но предоставил гораздо менее элегантное решение) разделить каждое наблюдение за лечением на отдельный набор данных (у меня меньше 600 процедур). Вот макрос, который у меня работает, но не выполняет то, что я хочу. (Поскольку я новичок в Stack Overflow, вы можете указать мне, является ли это изменение TMI, если я должен был открыть другой вопрос или просто дать всю эту информацию в исходном вопросе - я очень признателен за вашу помощь и буду хотел бы быть как можно меньше обузой).
%macro Matching(datatreatment=, datacontrol=, method=, numberofcontrols=, caliper=, ccpercent=,
replacement=, out=);
/* Create copies of the treated units if N > 1 */;
data _Treatment0(drop= i);
set &datatreatment;
do i= 1 to &numberofcontrols;
RandomNumber= ranuni(12345);
output;
end;
run;
/* Randomly sort both datasets */
proc sort data= _Treatment0 out= _Treatment(drop= RandomNumber);
by RandomNumber;
run;
data _Control0;
set &datacontrol;
RandomNumber= ranuni(45678);
run;
proc sort data= _Control0 out= _Control(drop= RandomNumber);
by RandomNumber;
run;
data Matched (keep = cikSelectedControl atControl roacontrol roatreat fyear industry MatchedToTreatcik atTreat);
length atC 8;
length cikC 8;
/* Load Control dataset into the hash object */
if _N_= 1 then do;
declare hash h(dataset: "_Control", ordered: 'no');
declare hiter iter('h');
h.defineKey('cikC');
h.defineData('roac','atC','cikC');
h.defineDone();
call missing(cikC, atC, roac);
end;
/* Open the treatment */
set _Treatment;
%if %upcase(&method) ~= RADIUS %then %do;
retain BestDistance 99;
%end;
/* Iterate over the hash */
rc= iter.first();
if (rc=0) then BestDistance= 99;
do while (rc = 0);
/* Caliper */
%if %upcase(&method) = CALIPER %then %do;
if (atT - &caliper) <= atC <= (atT + &caliper) then do;
ScoreDistance = abs(atT - atC);
if ScoreDistance < BestDistance then do;
BestDistance = ScoreDistance;
cikSelectedControl = cikC;
atControl = atC;
MatchedToTreatcik = cikT;
atTreat = atT;
end;
end;
%end;
/* Calculated caliper */
%if %upcase(&method) = CC %then %do;
ccdist = &ccpercent*atT;
if (atT - ccdist) <= atC <= (atT + ccdist) then do;
ScoreDistance = abs(atT - atC);
if ScoreDistance < BestDistance then do;
BestDistance = ScoreDistance;
cikSelectedControl = cikC;
atControl = atC;
MatchedToTreatcik = cikT;
atTreat = atT;
ROAControl = roaC;
ROATreat=roat;
end;
end;
%end;
/* NN */
%if %upcase(&method) = NN %then %do;
ScoreDistance = abs(atT - atC);
if ScoreDistance < BestDistance then do;
BestDistance = ScoreDistance;
cikSelectedControl = cikC;
atControl = atC;
MatchedToTreatcik = cikT;
atTreat = atT;
end;
%end;
%if %upcase(&method) = NN or %upcase(&method) = CALIPER or %upcase(&method) = CC %then %do;
rc = iter.next();
/* Output the best control and remove it */
if (rc ~= 0) and BestDistance ~=99 then do;
output;
%if %upcase(&replacement) = NO %then %do;
rc1 = h.remove(key: cikSelectedControl);
%end;
end;
%end;
/* Radius */
%if %upcase(&method) = RADIUS %then %do;
if (atT - &caliper) <= atC <= (atT + &caliper) then do;
cikSelectedControl = cikC;
atControl = atC;
MatchedToTreatcik = cikT;
atTreat = atT;
output;
end;
rc = iter.next();
%end;
end;
run;
/*to download datasets from wrds to investigate*/
proc download data=matched; run;
proc download data=_Control; run;
/* Delete temporary tables. Quote for debugging */
proc datasets NOLIST; /*Nolist option should prevent printing of dataset list*/
delete _:(gennum=all);
run;
data &out;
set Matched;
run;
proc datasets NOLIST; /*Nolist option should prevent printing of dataset list*/
delete Matched;
%mend Matching;
%Matching(datatreatment= Ta220092, datacontrol= ca220092, method= cc,
numberofcontrols= 100, caliper=1, ccpercent=.2, replacement= no, out= matchtest4);
Еще одно замечание: я буду запускать этот матч через PC SAS в системе WRDS, которая работает быстрее и не приведет к зависанию моего компьютера во время обработки.
proc surveyselect
, он может сделать множество выборок (Google Don't be loopy SAS). Разделение наборов данных усложняет обслуживание и делает ваши библиотеки и код беспорядком. - person Joe   schedule 13.07.2014