【发布时间】:2020-04-08 03:26:27
【问题描述】:
我对 SAS 还很陌生,我很难理解如何用 SAS 宏语言编写数据驱动的程序。但是,proc lua 对我来说很有意义。尽管如此,我想知道两者。
下面的代码——尽管它可能很愚蠢——说明了我正在努力解决的概念。它会随机列出猫的名字,然后找出哪些猫很顽皮,哪些猫很乖。然后它会打印出一份圣诞清单,让我知道应该为哪些猫买礼物,以及我可以为每只猫花多少钱。
我在翻译/实现为 SAS 宏语言时遇到困难的部分代码是:
1) 找出第 j 只猫的后缀的部分,然后将其打印到日志中。如何动态更改宏变量的值,然后在宏循环中使用它们将某些内容写入日志?有没有办法在宏中使用“call symput”或“symget”?
2) 如何在宏循环中写入多个数据集,类似于我在下面所做的。
3) 如何在sas宏中调用proc fcmp编译的自定义函数来控制宏的流程。
* This macro create a list of cat names;
%macro getsomecats(num);
%local mycat;
%let mycat = cat1;
%do j = 2 %to #
%let mycat = &mycat.%str( cat)&j.;
%end;
&mycat
%mend;
* SAS macro that duplicates the Excel RANDBETWEEN function. Taken from
http://blogs.sas.com/content/iml/2015/10/05/random-integers-sas.html;
%macro RandBetween(min, max);
(&min + floor((1+&max-&min)*rand("uniform")))
%mend;
* Get the number of cats that will be in our list;
data _null_;
seed = %randbetween(1,50);
call symputx('myseed',seed);
run;
* Make a random list of cat names;
%let morecats = %getsomecats(&myseed.);
* Reference some custom functions compiled with proc fcmp;
options cmplib=(MY_FUNCS.PURE_MATH);
libname NUMBERS '/folders/myfolders';
* Make two data sets: one for all of my cats, and another for
the cats that I should by Christmas presents;
proc lua;
submit;
-- Import Lua libraries
require 'string'
require 'math'
-- If the tables I want to create exist, then delete them.
if sas.exists('my_cats') then
sas.submit([[
proc delete data=my_cats;
]])
print('my_cats deleted')
end
if sas.exists('xmas_list') then
sas.submit([[
proc delete data=xmas_list;
]])
print('xmas_list deleted')
end
-- Set up some data sets
sas.new_table('my_cats', {
{name='Name', type='C', length=8},
{name='Status', type='C', length=8},
{name='Gender', type='C', length=6}
})
sas.new_table('xmas_list', {
{name='Name', type='C', length=8},
{name='Status', type='C', length=8},
{name='Gender', type='C', length=6},
{name='Budget', type='N', length=8}
})
-- Create data set handels for our new data set
local dsh1 = sas.open('my_cats', 'u')
local dsh2 = sas.open('xmas_list', 'u')
-- Declare some useful variables
local suffix, status, gender, name
local ub = 1 -- upper bound for 'for' loop
local mystr = sas.symget("morecats")
-- Find out upper bound on number of cats
for j = 1, string.len(mystr) do
if mystr:sub(j,j) == ' ' then ub = ub + 1 end
end
mystr = nil -- we do not need mystr anymore
print('Making my christmas list:') -- Write header in log
for j = 1, ub do
-- Create a suffix for jth cat; I am very confused about
-- how to do this in the SAS macro language.
if j % 10 == 1 and j % 100 ~= 11 then suffix = 'st'
elseif j % 10 == 2 and j % 100 ~= 12 then suffix = 'nd'
elseif j % 10 == 3 and j % 100 ~= 13 then suffix = 'rd'
else suffix = 'th' end
-- Find out if the jth cat has been naughty or nice.
-- 'isprime' is a custom function compiled with proc fcmp,
-- it returns 1 if a number is prime and 0 if it is composite.
if sas.isprime(j) == 1 then
status = 'naughty'
else
status = 'nice'
end
-- Assign the cat a gender randomly. I would like to
-- know how to this in the SAS macro language, including
-- how to use a list so that I can reference the two different
-- charchteristics of gender.
if sas.ranuni(0) < .5 then
gender = {'male', 'he'}
else
gender = {'female', 'she'}
end
-- Get the cats name; scan the macro variable
-- 'morecats' for the jth entry.
name =sas.scan(sas.symget("morecats"),j)
-- Write information in our log about this cat,
-- again, I cannot figure out how to deal with the
-- suffix part here.
print('My '..j..suffix.." cat's name is "..name..
', and '..gender[2]..' is usually '..status)
-- Add the jth cat to my data set of cats
sas.append(dsh1)
sas.put_value(dsh1,"Name", name)
sas.put_value(dsh1,"Status", status)
sas.put_value(dsh1,"Gender", gender[1])
sas.update(dsh1)
-- If the jth cat is usually nice then, add him or her
-- to the data set of cats that need to by Christmas
-- presents for.
if status == 'nice' then
local budget = 10 * sas.phi(math.random(30))
sas.append(dsh2)
sas.put_value(dsh2,"Name", name)
sas.put_value(dsh2,"Status", status)
sas.put_value(dsh2,"Gender", gender[1])
sas.put_value(dsh2,"Budget", budget)
sas.update(dsh2)
end
end
sas.close(dsh1)
sas.close(dsh2)
endsubmit;
run;
proc print data=xmas_list;
var _all_;
sum Budget;
run;
示例输出:
示例日志:
Making my christmas list:
My 1st cat's name is cat1, and she is usually nice
My 2nd cat's name is cat2, and he is usually naughty
My 3rd cat's name is cat3, and she is usually naughty
My 4th cat's name is cat4, and she is usually nice
My 5th cat's name is cat5, and she is usually naughty
My 6th cat's name is cat6, and he is usually nice
My 7th cat's name is cat7, and she is usually naughty
My 8th cat's name is cat8, and she is usually nice
【问题讨论】:
-
操作实际数据应该使用 SAS 代码,而不是 MACRO 代码或 LUA 代码。
-
如果没有问题描述,很难判断您的程序在做什么。但是快速看一下,看起来对宏的唯一需要是如果您想要制作一些参数,例如要生成多大的一组猫或使用什么随机数种子。否则,它看起来像是不需要代码生成的直接数据操作。