提问人:Segeana 提问时间:9/15/2023 更新时间:9/20/2023 访问量:30
宏和设置局部变量中的 SAS 语法错误
SAS Syntax error in macro and setting up local variables
问:
我是SAS的新手。我从两个 excel 电子表格中导入了数据。从第一个开始,我计算了新变量名称 Sorptivity 和 Kfs。此步骤工作正常。然后,我将新创建的变量(其中有 24 个变量)与第二个表(有 237 个观测值)合并。第一个表中的 21 个观测值对应于第二个表中的 21 个独特的处理 x 块组合,因此实际上每个处理 x 块都会多次添加吸附率和 Kfs 值,对应于时间和 CI 条目(每个处理 x 块有 7 到 12 个时间和 CI 条目)。3 个“缺失条目”是从第二个表中删除的异常值。
我想运行一个非线性模型(CI = 吸附率 * sqrt(Time) + Kfs)。它必须为我提供每个处理 x 块组合的输出。我希望将 Time、CI、Sorptivity 和 Kfs 的原始值以及与每次时间测量对应的预测 CI 值作为输出。
在 ChatGPT 的帮助下,我设置了以下代码,但我遇到了一个错误,并且由于 erorr 在宏中,我收到了一个额外的假脱机错误,这意味着我无法确定错误在哪里。我希望有人能帮我弄清楚问题出在哪里以及如何纠正它。
%macro run_model(treatment, block, time, ci, s, k);
data temp;/* Create local macro variables */
merge infiltration (where=(Treatment = "&treatment" and Block = "&block"))
InfilNewData (where=(Treatment = "&treatment" and Block = "&block"));
by Treatment Block;
Time = &time;
CI = &ci;
Sorptivity = &s;
Kfs = &k;
run;
proc nlin data=temp;
parms Sorptivity = &s Kfs = &k;
model CI = Sorptivity * sqrt(Time) + Kfs;
output out=PredictedCI_&treatment Block=Block Time=Time CI=CI Sorptivity=Sorptivity Kfs=Kfs predicted=PredictedCI;
run;
data PredictedCI_&treatment;/* Add a Treatment group identifier to the output */
set PredictedCI_&treatment;
Treatment = "&treatment";
Block = "&block";
run;
%mend;
%macro run_all_models;
%local treatment_list block_list s_list k_list time_list ci_list;
/* Create macro variable lists within the macro */
proc sql noprint;
select distinct Treatment into :treatment_list separated by ' ' from InfilDF;
select distinct Block into :block_list separated by ' ' from InfilDF;
select distinct Sorptivity into :s_list separated by ' ' from InfilNewData;
select distinct Kfs into :k_list separated by ' ' from InfilNewData;
select distinct Time into :time_list separated by ' ' from InfilDF;
select distinct CI into :ci_list separated by ' ' from InfilDF;
quit;
/* Loop over the macro variables and run the models */
%do i = 1 %to %sysfunc(countw(&treatment_list));
%let current_treatment = %scan(&treatment_list, &i);
%let current_block = %scan(&block_list, &i);
%let current_s = %scan(&s_list, &i);
%let current_k = %scan(&k_list, &i);
%let current_time = %scan(&time_list, &i);
%let current_ci = %scan(&ci_list, &i);
%run_model(¤t_treatment, ¤t_block, ¤t_time, ¤t_ci, ¤t_s, ¤t_k);
proc print data=PredictedCI_¤t_treatment;
run;
%end;
%mend;
%run_all_models;
在run_model宏中,我最初设置为获取仅来自名为 InfilDF 的组合 DF 的局部变量,该 DF 具有上述所有 4 个数值变量。然后,我尝试将其更改为您在此处看到的代码,该代码从两个原始表中提取变量。结果/错误是一样的:data temp
WHERE (Treatment='Biochar10tha') and (Block='Block1');
22: LINE and COLUMN cannot be determined.
ERROR 22-322: Syntax error, expecting one of the following: ;, (, /, ESS, H, J, L95,
L95M, LCL, LCLM, LMAX, OUT, P, PARMS, PRED, PREDICTED, PRES, PROJRES,
PROJSTUDENT, PRSTUD, R, RESEXPEC, RESIDUAL, REXPEC, SSE, STDI, STDP, STDR,
STUDENT, U95, U95M, UCL, UCLM, WEIGHT.
76: LINE and COLUMN cannot be determined.
ERROR 76-322: Syntax error, statement will be ignored.
数据和代码可在以下网址获得:https://github.com/AnelD13/SAS_infiltration。我发现错误的两个主要位置是在设置临时 DF 的第一个宏和模型代码本身中。吸附率和 Kfs 宏变量的设置方式可能存在问题,因为以前的错误都指向了这一点。
答:
对于任何寻找类似答案的人,我最终简化了它。我问题中的宏创建了局部变量,这些变量旨在以迭代方式输入到 nlm 中,目的是创建一个“旁循环”。我来自 R 背景,并在那里使用了 smiliar 方法。一旦模型遍历了所有处理变量和模块变量,它就应该输出到新的数据框,使用初始输入数据框中的变量以及新创建的变量。我让它在 3 次 spearate 场合工作,但不知道如何或为什么,但预测的输出总是相差甚远,并且数据帧输出也具有来自初始数据帧的错误输入变量值。
根据上面的评论,我尝试使用 SAS 的内置 nlin 函数和 by-statement 来循环访问 Treatment 和 Block。我已经在其他程序中使用了副语句,但在我提出问题之前没有想过要为这个程序这样做。下面的代码与宏中的过程基本相同,但没有尝试在外部循环它。然后,对两个数据帧进行简单的合并,而不是按照宏循环进行合并。
proc nlin data=InfilDF;
parms Sorptivity=0.01 Kfs=0.01;
model CI = Sorptivity * sqrt(Time) + Kfs;
by Treatment Block;
output out=PredictedResults predicted=PredictedCI;
run;
data InfilPredicted;
retain Block Treatment Time CI Infiltration Sorptivity Kfs; /* I had to do this as my Time
variable showed up empty*/
merge InfilDF PredictedResults;
by Treatment Block;
run;
proc sort data=InfilPredicted;
by Treatment Block Time;
run;
proc print data=InfilPredicted;
run;
这是一个更简单的解决方案,与SAS程序中的许多简单性一致。它可以防止添加不必要的代码或变量。
评论