SAS 循环与数组

SAS提供了循环语句以满足在编程中需要多次执行相同操作的情 况。有时还需要对不同的变量执行相同的操作,此时可定义SAS数组,并通过数组名和下标来引用这些变量。

1 循环

SAS循环语句通常有如下几种形式:迭代DO语句、DO WHILE语句 和DO UNTIL语句。

1.迭代DO语句

迭代DO语句的基本形式如下:

DO  索引变量=开始值  <TO  结束值>  <BY递进值>  <WHILE(表达式)>  <UNTIL(表达式)>;
… SAS语句…
END;

其中:

  • ·索引变量用于指定一个变量,若该变量不存在,则创建新变量。DO语句和END语句之间的语句称为DO组,索引变量的值会控制DO组 的执行。
  • ·开始值指定索引变量的初始值,可以是表达式或表达式序列。DO组的执行从“索引变量=开始值”开始。在循环的第一个迭代开始前,对开始值求值。如果结束值和递进值不存在,那么开始值可能是一系列 项,则DO语句的形式如下。
DO  索引变量=项1  <,  …项n>;

项1~项n可以是数字常量、字符常量或变量。SAS为列表中的每个 项执行一次DO组。

  • ·结束值指定索引变量的结束值。当开始值和结束值都存在时,DO 组执行直到下面任意一种情况发生时循环执行结束:索引变量的值超过 结束值;DO组中存在指示退出循环的语句,例如LEAVE语句、GO TO 语句;如果有WHILE或UNTIL选项,则WHILE之后的表达式不满足或 UNTIL之后的表达式满足(可参考后面对DO UNTIL语句和DO WHILE 语句的介绍)。
  • ·递进值指定一个数字,或者是产生数字值的表达式,来控制索引 变量的增量。递进值在循环执行前进行计算。因此,在DO组内对递进 值的修改不会影响循环迭代次数。每次迭代后,索引变量的值为其当前 值的基础上增加递进值。如果未指定递进值,则索引变量的值增加1。
data work.square;
do x= to by ;
y = x**;
output;
end;
run;
proc print data=work.square;
run;

2.  DO UNTIL语句

DO UNTIL语句重复执行DO循环中的语句,直到条件为真。DO UNTIL语句的基本形式如下:

DO  UNTIL  (表达式);
...SAS语句...
END;

表达式可是任意的SAS表达式。DO UNTIL语句中至少包含一个表 达式,也可以包含多个表达式。在DO循环中的语句执行完成后将对表 达式求值。所以,DO循环至少被执行一次。

将给定字符串中包含的各个单词分开写入数据集中。 在DO循环中使用SCAN函数依次读取字符串中的单词,并存储在变量word中且输出。LENGTHN函数用于判断循环结束的标志。当SCAN 函数扫描到字符串结尾,word值为空时,LENGTHN函数返回0,循环 结束。

代码如下:

data  work.all;
length word $;
drop string;
string='The quick brown fox jumps over the lazy dog.';
do until(lengthn(word)=);
count+;
word=scan(string, count);
output;
end;
run;
proc print data=work.all noobs;
run;

3.DO WHILE语句

DO WHILE语句在条件为真时重复执行DO循环。DO WHILE语句 的基本形式如下:

DO  WHILE  (表达式);
...SAS语句...
END;

表达式可是任意的SAS表达式。DO UNTIL语句中至少包含一个表 达式,也可以包含多个表达式。在DO循环中的语句被执行前先对表达式求值。如果第一次执行时表达式为假(false),DO循环不会被执行。

将给定字符串中包含的各个单词分开写入数据集中。 代码如下:

data  work.all;
length word $;
drop string;
string='The  quick  brown  fox  jumps  over  the  lazy  dog.';
word=scan(string, );
do while(lengthn(word)>);
count+;
word=scan(string, count);
output;
end;
run;

因为要WHILE表达式必须成立才会执行DO循环,也就是说在执行 到DO WHILE语句之前,word不能为空或缺失值,所以代码中先对word 值赋值(word可以赋值为其他任何不为空的字符值)。DO循环中,当 SCAN函数扫描到字符串结尾,word值为空时,LENGTHN函数返回0,不满足条件lengthn(word)>0,循环结束。所生成的数据集与例3.25的 结果一样,这里不再给出。

下面是对3种循环语句的比较:

  • ·迭代DO语句基于索引变量值重复执行DO语句和END语句之间的SAS语句。使用迭代DO语句较容易控制循环次数。
  • ·DO UNTIL语句重复执行在DO循环中的语句,直到条件为真。DOUNTIL语句在每次DO循环迭代结束后检查条件。
  • ·DO WHILE语句在条件为真时重复执行DO循环中的语句。DO WHILE语句在每次DO循环迭代开始前检查条件。

2  SAS数组

如果需要对许多变量做相同的操作,虽然可以通过写一系列赋值语句来实现,使用数组可以简化程序代码。

数组是一组以特殊顺序排列并由数组名标识的SAS变量。只要一组变量名都是同一类型,例如都是数值型或字符型,就可以为该组变量定 义一个数组。这些变量可以是数据集中已经存在的,也可以是要创建的 新变量。数组仅仅在当前DATA步中存在,在同一DATA步中,数组按 名字区分。SAS数组不是一种数据结构,只是临时标识一组变量较方便 的方法,在这点上SAS数组不同于其他编程语言中的数组。

1.数组定义及引用

在DATA步中使用ARRAY语句定义数组。定义数组的基本形式如 下:

ARRAY  数组名  {下标}   <$>   <长度>  <数组元素>  <(初始值列表)>;

其中:

  • ·数组名是指定给数组的名称。该数组名在同一DATA步中不能与任何其他变量名或关键字重名。其命名需遵循SAS变量的命名规范(不超 过32个字符,以字母或下划线开始,可包含字母、数字和下划线)。
  • ·下标可以有多种形式,通常为指定数组元素个数、上下边界或*。*表示通过计算数组元素个数确定数组下标。
  • ·$指定数组中的元素是字符元素。如果数组元素是数字元素或先前 已经定义的字符元素,则不需要使用$。
  • ·长度指定先前未指定长度的元素的长度。
  • ·数组元素指定组成数组的元素名称。
  • ·初始值列表给出数组中对应元素的初始值,以空格隔开。定义数组时的括号可以是()、{}或[]。定义数组时的下标形式指定了数组维度、各个维度的下边界和上边界。

还可以通过不同格式的下标指定多维数组,多个维度之间用逗号(,)分隔,同一个维度内的上下边界使用冒号(:)分隔,如表3.8所示。

数组元素可以是数值型或字符型,并且可以以任何顺序列出,其个数必须等于括号{}中给出的下标值。

数组元素可以是已经存在的变量或不存在的变量,当数组元素是不存在的变量时,SAS会创建新变量。除了列出变量外,变量可以是关键 字_NUMERIC_、_CHARACTER_或_ALL_。

还可使用关键字_TEMPORARY_来创建临时数据元素。临时数据元素不会出现在输出数据集中,并且其值总是自动保持,而不会在DATA 步的每次迭代开始时自动设置为缺失值。临时数组元素仅用于计算,如果要保留计算结果,需要将结果赋值给其他变量。使用临时数组元素的 好处是可以提高性能。

使用数组名引用变量时,要给出数组名和该变量的下标。例如,使 用如下ARRAY语句定义变量STORE,共4个元素,分别为变量Macys、Penneys、Sears和Target。

array  Store  {} Macys  Penneys  Sears  Target;

使用数组名引用变量时,STORE{1}是变量Macys,STORE{2}是Penneys,STORE{3}是Sears,STORE{4}是Target。 如果定义数组时指定了上下边界,例如:

array  Month  {:}  April  May  June;

则Month{4}是变量April,Month{5}是变量May,Month{6}是变量June。

这样就可以在循环中通过改变数组下标来操作每个数组元素对应的 变量,所以数组经常在DO组中使用。

2.数组函数

SAS提供了DIM、HBOUND和LBOUND函数返回数组中指定维度 的元素个数、上边界和下边界。

DIM函数返回一维数组中的元素个数或多维数组中指定维度中的元素个数。其形式如下:

DIM<n>(数组名)或DIM(数组名,  维度)

HBOUND函数返回一维数组的上边界或多维数组中指定维度的上 边界。其形式如下:

HBOUND<n>(数组名)或HBOUND(数组名,  维度)

LBOUND函数返回一维数组的下边界或多维数组中指定维度的下边 界。其形式如下:

LBOUND<n>(数组名)或LBOUND(数组名,  维度)

其中:

  • ·n指定维度的整型常量。如果未指定n值,则返回数组的第一维的结果。
  • ·数组名指定在同一DATA步中先前定义的数组名称。
  • ·维度是指定维度的数字常量、数字变量或数字表达式。

3.DO循环中引用数组元素 将数组与迭代DO语句结合使用,在对用数组所表示的变量进行处理时会变得简单。其基本形式如下:

DO  索引变量=  TO  数组元素个数;
… SAS语句…
END;

使用数据集saslib.revenue_quarter制定明年的销 售计划,预期各季度的销售额为今年的150%。

代码如下:

data  saslib.revenue_2014;
set saslib.revenue_quarter;
array Quarter {} Rev_Q1-Rev_Q4;
do i= to ;
Quarter{i} = Quarter{i}*1.5;
end;
drop i;
run;

其中:

  • ·ARRAY语句定义了数组Quarter,其元素个数为4。因为变量 Rev_Q1到Rev_Q4在输入数据集中存在,所以该数组只是引用存在的变 量Rev_Q1到Rev_Q4,并不创建新变量。这里数组元素使用了简化的表 达方式。
  • ·在DATA步的每次迭代中,通过在DO循环中引用Quarter{1}到 Quarter{4}来分别操作变量Rev_Q1到Rev_Q4,将销售额在现有销售数据 的基础上增加50%。

数据集saslib.revenue_2014在VIEWTABLE窗口打开如图所示。

SAS 循环与数组的更多相关文章

  1. *使用while循环遍历数组创建索引和自增索引值

    package com.chongrui.test;/* *使用while循环遍历数组 *  *  * */public class test {    public static void main ...

  2. 关于for循环删除数组内容出现的问题

    昨天用for循环进行数组去重的时候出现的问题, 首先,用双重for循环把前一个和所有后面的元素进行比较,如果相等则删除. 但是,如果数组里面有三个以上连续相等的元素的时候,就会出现问题. var ar ...

  3. JavaScript 中 for in 循环和数组的问题

    本文由 伯乐在线 - ElvisKang 翻译,进林 校稿.未经许可,禁止转载!英文出处:adripofjavascript.com.欢迎加入翻译小组. JavaScript的for…in循环用于迭代 ...

  4. JavaScript基础精华03(String对象,Array对象,循环遍历数组,JS中的Dictionary,Array的简化声明)

    String对象(*) length属性:获取字符串的字符个数.(无论中文字符还是英文字符都算1个字符.) charAt(index)方法:获取指定索引位置的字符.(索引从0开始) indexOf(‘ ...

  5. swift基本用法-for循环遍历,遍历字典,循环生成数组

    // Playground - noun: a place where people can play import UIKit //--------------------------------- ...

  6. PHP(方法 函数 循环 和 数组 查找)

    循环 和 数组 查找 顺序查找 二分法查找 冒泡排序 方法 函数 定义:一堆代码的集合叫做函数(满足条件下“一堆”) 语法,定义,调用,参数列表(形参,实参),返回值 两种方法: function 方 ...

  7. js循环遍历数组

    一维数组的遍历 <script> //循环遍历数组 var animals = ["cat",'dog','human','whale','seal']; var an ...

  8. for循环遍历数组(数组1)

    package com.mon10.day24; import java.util.Scanner; /** * 类说明 :计算学生的总成绩和平均分 * @author 作者 : chenyanlon ...

  9. LeetCode 81 Search in Rotated Sorted Array II(循环有序数组中的查找问题)

    题目链接:https://leetcode.com/problems/search-in-rotated-sorted-array-ii/#/description   姊妹篇:http://www. ...

随机推荐

  1. myeclipse2017+ssm+tomcat8+jdk1.8

    练习上手ssm项目 工具:myeclipse2017,spring4,jdk1.8,tomcat8 搭建链接:https://www.cnblogs.com/cuglkb/p/6734666.html ...

  2. cxgrid属性说明,每次用的时候费时费力查找。

    由层得到数据表名: procedure TFB_PatientWaiting.cxgrdbtblvwGrid1DBTableView_MyPatienWaitingDblClick( Sender: ...

  3. register关键字

    register关键字从c++11开始已经弃用了,但是在看SuRF代码(https://www.cnblogs.com/YuNanlong/p/10235793.html) 的时候,还是看到了这个关键 ...

  4. 使用IntelliJ IDEA 配置Maven

    创建一个本地仓库路径 配置本地仓库路径 配置maven环境变量 配置maven环境变量 打开命令输入 : mvn version,配置成功如下图所示: 在IntelliJ IDEA中配置maven f ...

  5. python中os模块操作目录与文件名小结

    (1). 创建目录: SigleDir = 'sigle_layer' MultiDir = 'D:\\Web\\multi_layer' 创建单层目录: os.mkdir(SigleDir) 创建多 ...

  6. 遇到的[]bug

    "Runtime Error Message:reference binding to null pointer of type 'struct value_type' Last execu ...

  7. Go语言编程读书笔记:Go channel(1)

    Channel是Go语言在语言级别提供的goroutine间的通信方式.我们可以用channel在两个或多个goroutine之间传递消息.channel是进程内的通信方式,因此通过channel传递 ...

  8. I/O多路复用、协程、线程、进程

    select注册fd,阻塞,当有fd状态改变时返回,确认对应的fd,做下一步处理.简单来说就是先注册,注册完后休眠并设置一个定时器醒来查看,有事件就通知来取,进行后续动作,没事件就继续睡,再设闹钟.用 ...

  9. ThinkPHP3.2 --- 中文乱码问题

    在thinkphp中初次运行时 会出现中文乱码问题,解决方法也很简单 只需要在入口文件index.php加上这段代码即可: <?php header("Content-Type: te ...

  10. 通行导论-IP数据网络基础(2)

    传输控制协议(TCP) 差错控制:TCP使用差错控制提供可靠性,包括检测受到损伤.丢失.失序的报文段 实现方法:1.16位检验和,2.确认机制:采用确认证实收到的报文段,3.重传(设置一个重传超时RT ...