2016-11-11 3 views
0

Я пытаюсь построить таблицу 2, написав ниже код SAS, но я получаю таблицу 1. Я не мог понять, что я пропустил. Помогите с благодарностью. Спасибо.SAS SymputX и функция Symget

 &counter = 4 

    data new;set set1; 
    total = 0; 
    a = 1; 
    do i = 1 to &counter; 
     call symputX('a',a); 
     total = total + Tem_&a.; 
     a = symget('a')+1; 
     call symputX('a',a); 
    end; 
    run; 



     Table 1 
     ID Amt Tem_1 Tem_2 Tem_3 Tem_4 total 
     4 500 1  4  5 900 3600 
     5 200 50  100  200  0  0 
     9 50 40  0  0  0  0 
     10 500 70  100  250  0  0 



    Table 2 
    ID Amt Tem_1 Tem_2 Tem_3 Tem_4 total 
     4 500 1  4  5 900  910 
     5 200 50  100  200  0  350 
     9 50 40  0  0  0  40 
    10 500 70  100  250  0  420 

ответ

2

Вы не можете использовать SYMPUT и SYMGET таким образом, к сожалению. Хотя вы можете использовать их для хранения/получения значений макропеременной, вы не сможете изменить код, отправленный компилятору после выполнения.

В принципе, SAS должен определить машинный код для того, что он должен делать на каждой итерации цикла шага данных, прежде чем он посмотрит на любые данные (это называется компиляцией). Таким образом, проблема заключается в том, что вы не можете определить tem_&a. и ожидать, что вам будет разрешено изменить то, что _&a. во время исполнения, потому что это изменит то, что должен сделать этот машинный код, и SAS не может подготовиться к этому достаточно.

Итак, то, что вы написали &a., будет разрешено при компиляции программы и независимо от того, какое значение имеет значение &a., прежде чем ваш шаг данных будет равен tem_&a.. Предположительно, в первый раз, когда вы запустили это, он ошибся (&a. does not resolve, а затем ошибка в & была незаконна в именах переменных), а затем в итоге call symput выполнил свою работу, а &a получил в ней 4 в конце цикла и навсегда больше вашего tem_&a. разрешен к tem_4.

Решение? Не используйте для этого макросы. Вместо этого используйте массивы.

data new; 
    set set1; 
    total = 0; 
    array tem[&counter.] tem_1-tem_&counter.; 
    a = 1; 
    do i = 1 to &counter; *or do i = 1 to dim(tem); 
     total = total + Tem[i]; 
    end; 
run; 

Или, конечно, просто сразу их суммируйте.

data new; 
    set set1; 
    total = sum(of tem_1-tem_4); 
run; 

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

data new; 
    set set1; 
    total = 0; 
    %do i = 1 %to &counter; 
     total = total + Tem_&i.;   
    %end; 
    run; 
+0

Большое вам спасибо, Джо! –

+0

@Joe Вероятно, необходимо заменить жестко закодированную верхнюю границу ссылкой на макроопределение переменных или удалить ссылку на макро переменную. Поскольку он стоит сейчас, у вас будет проблема, если COUNTER не будет 4. – Tom

+0

Согласитесь @tom, хотя причина, по которой я не делал этого, заключалась в том, чтобы не очень сильно отклонять код от исходного кода, чтобы показать параллели. – Joe

Смежные вопросы