Nobs sas data step where

[学习 分享] 宏 变量 的 定义 方式 及 几种 使用 技巧 自动 获取 路径 [分享]

Macro 是 SAS 编程 不可 缺少 的 一部分 , Macro 的 好处 很多 (此处 省略 若干 字)) , 当然 这 也是 接着 前面 的 基础 篇 写 的 ~ 这 也是 一个 Macro 中 的 基础 篇。


宏 变量 定义 的 三种 方式


说到 Macro , 那么 就 不得不 说 宏 变量 , 宏 变量 的 是 啥呢? 可以 理解 成 和 其它 编程 语言 中 的 变量 一样 , 在 内存 中 中 创建 了 一个 空间 (给 这个 空间 一个 标记 , 宏 变量 的 名称) , 然后 将 一些 值 放到 这个 内存 空间 中 (这 就是 定义 宏 变量 的 过程) , 好吧 , 我 是 一个 一个 不善 解释 的 人 , 没 理解 的 还是 自行 百度 领悟。 那么 就 来 看看 如何 来 定义 Macro 变量。

% LET


% let 方式 定义 宏 变量 : 这个 是 最 简单 、 最 直接 的 赋值 定义 的 方式.

将 值 直接 赋值 给 宏 变量 .... 那么 来看 一个 简单 的 例子.


% let macvar1 = 2018, where hai shi yi ge dan shen dog;
% put NOTE: 宏 变量 macvar1 的 值 是: & macvar1 .;

见 上面 的 这个 例子 , 小编 将 一句话 直接 赋值 给 宏 变量 , 通过% put 见 下面 一句话 打印 到 日志 , 这个 这个 时候 通过 解析 符号 来 解析 定义 的 的 Macro 变量。 来 看看 日志 的 是 什么 样 的. ..


看 蓝色 部分 的 哪一 行话 , & macvar1 那个 地方 已经 别 替换 了 ... 显示 的 是 宏 变量 的 值 ....

那么 在 实际 编程 中 ,% let 方式 定义 宏 变量 用 的 多么 , 答案 是 显然 的 多! 最 常用 的 的 场景 之一 就是 定义 路径. 在 每个 项目 开始 编程 的 第一步, 最 开始 的 程序, 大概都是 Setlib, 设置 项目 夹子 / 与 建立 逻辑 库, 并将 路径 全部 赋值 给 相应 的 宏 变量 , 在 后续 的 编程 中, 如果 有 路径 的 引入, 将 全部 用 宏 变量 去 代替 , 为什么 要 这么做 呢?那 就是 将 项目 夹子 打包, 不管 移动 到 任何 地方, 无需 人工 修改 程序 内部 路径, 就 可以 直接 运行 程序 了 ... 当然 好处 不仅仅 如此, 接下来 小编 将 举出 一个 自动 获取 路径 , 建立 逻辑 库的 方式 ...

第 一种 :

% macro setups;
% global PATH PGMLIB PROJECT;
% LET CURRENTROOT =% upcase (% sysget (sas_execfilepath));
% LET PGMLIB =% upcase (% sysfunc (substr (& CURRENTROOT., 1,% index (% sysget (sas_execfilepath), \% sysget (sas_execfilename)))));
% PUT NOTE: & CURRENTROOT .;
% PUT NOTE: & PGMLIB .;
Libname dblib "& PGMLIB.";
% mend;% setups; 第二种 :
% macro setup;
% GLOBAL SETUP PGMLIB PATH PROJECT;
% LET SETUP =% upcase (% sysget (sas_execfilepath));
% LET PGMLIB =% sysfunc (prxchange (s / (. *) \. * / \ 1 /, - 1, & SETUP));
% LET PATH =% sysfunc (prxchange (s / (. *) \. * / \ 1 /, - 1, & PGMLIB));
% PUT NOTE: PGMLIB = & pgmlib .;
% PUT NOTE: PATH = & path .;
Libname dblib1 "& PGMLIB.";

% mend;
%set up;

这俩 段 代码 是 等效 的 , 原理 是 获取 当前 程序 所在 的 路径 , 然后 针对 此 路径 追溯到 前面 的 几 级 文件 夹 , 将 所需 的 路径 赋值 给 宏 变量 , 然后 在 通过 调用 宏 变量 去 定义 逻辑库 ... 在 编程 的 过程 中 , 是 可以 全程 不用 手动 输入 外部 路径 的 .... 都 可以 通过 宏 变量 代替 , 将来 将来 项目 夹子 不管 怎么 移动 , 都能 直接 运行 程序 的 .. 那么 在 来 看看日志。



CALL SYMPUT

CALL SYMPUT 定义 Macro 变量

如果 想 将 一个 数据 集中 的 观测 给 赋值 给 Macro 变量, 做 循环, 那么 就

可以 使用 此 方式 ... 那么 还是 举出 一个 例子 ..

% macro gtpgm;
filename temp1 pipe "dir E: \ macro \ *. sas / b";
data _null_;
infile temp1 truncover;
input fname $ char1000 .;
i = _n_;
call symput ('pgmn' || compress (put (_n_, best.)), strip (fname));
call symput ('nobs', strip (Max (I)));
run;
% put NOTE: 该 路径 下一 共有 & nobs. 个 sas 程序 文件, 名称 如下 :;
% do i = 1% to & nobs .;
% put NOTE: 第 & i. 条 观测 的 值 : && pgmn & i .;
%end;
% mend;
% gtpgm;

我 这里 是 将 某 路径 下 所有 的 sas 程序 名称 赋值 给 宏 变量 ...

实际 编程 应用 中 实际 是 非常 广 的, 比如 批量 导入 excel / csv 的 时候 自动 获取 文件 名称 , 将 将 文件 名称 赋值 给 宏 变量 , 通过 通过 循环 来 实现 批量 导入 导出 的 操作 ...

CALL SYMPUT 这种 方式 还是 一句话 : 特别 好用, 当然 也 有 一些 局限性 ..



PROC SQL INTO:

SQL 定义 宏 变量 是 特别 的 好用, 可以 将 一 列 观测 的 值 赋值 给 一个 宏 变量 , 也 可以 将 观测 逐条 逐条 赋值 ... 应用 场景 特别 广 那么 就 来 看看 几个 简单 的 例子 ...

% macro sqlptname;
proc sql noprint;
/ * 通过 数据 集 字典 dictionary.tables 来 获取 SASHELP.CLASS 数据 拥有 的 观测 个数, 变量 个数, 并将 其 分别 赋值 给 _nobs, _nvar * /
select compress (strip (put (nobs, best.))), compress (strip (put (nvar, best.))) into: _nobs,: _ nvar
from dictionary.tables where libname = upcase ("sashelp") and memname = upcase ("class");
/*SASHELP.VCOLUMN 里面 存储 了 很多 信息 ... 这里 是 将 SASHELP.CLASS 中 的 变量 名 以 空格 连接 起来 赋值 给 宏 变量 varlist * /
select NAME into: varlist separated by ""
from sashelp.vcolumn where libname = upcase ("sashelp") and memname = upcase ("class");
/ * 这里 将 SASHELP.CLASS 数据 集中 的 NAME 列 的 记录, 逐条 赋值 给 宏 变量 NAME1 NAME2 .... * /
select name into: name1-: name% left (& _ nobs.)
from sashelp.class;
quit;
/ * 在 日志 显示 宏 变量 的 值 * /
% put NOTE: SASHELP 一 共有 记录:% sysfunc (strip (& _ nobs.)), 变量:% sysfunc (strip (& _ nvar.));
% put NOTE: 变量 分别 为:% sysfunc (strip (& varlist.));
% do i = 1% to & _nobs .;
% put NOTE: 第 & i. 条 观测 的 对应 的 名称 为 : && Name & i .;
%end;
% mend;
% sqlptname;

看 上面 的 SQL 中 定义 宏 变量 , 实际 是 有 俩 种 , 有 没有 发现 ... 没 发现 的 话 , 在 仔细 看看



仔细 看了 还没 发现 , 那么 就 来 看看 小编 设置 的 SQL 定义 宏 变量 的 快捷 方式 的 代码 块 (2 种) ...

proc sql noprint;
select count (distinct name) into: nn from class;
select distinct name into: name1-: name% left (& nn.)
from class
;
quit;
proc sql noprint;
select NAME into: varlist separated by "," from _varstemp10;
quit;