其实我是不喜欢SAS的。当然,我不喜欢她,并不代表她不好,实际上在某些应用场景下SAS是款很优秀的软件。我的数据分析之路始于R,品尝过R的灵活与简洁(不论是软件安装还是语法)后,再来学习SAS,的确提不起兴致。然而由于:1.导师的项目数据量较大(几Gb到几十Gb);2.之前的项目代码师兄已经用SAS很优美地实现了;3.我莫名地当上了该项目负责人,要带着师弟师妹做该项目。我也只好硬着头皮学习SAS。奈何现在脑力大不如前,看的东西越来越记不住,于是下定决心梳理一下SAS相关知识。

1. DATA步简介

在SAS中,我们使用DATA步来读入数据,DATA步在读入数据时实际上有两个阶段:编译(compilation)和执行(execution)。过程如下:

  1. 在编译阶段中,逐个扫描语句,如果发现语法错误,SAS报错并终止运行;如果编译阶段中没有发现任何语法错误,进入执行阶段。
  2. 在执行过程中,DATA部读入第一条数据,在SAS中创建第一条观测;读入第二条数据,在SAS中创建第二条观测;读入第三条数据,在SAS中创建第三条观测……直至读入最后一条数据并在SAS中创建最后一条观测。我们可以把这个过程当做隐式循环(和DO,DO WHILE,DO UNTIL语句区分,它们是显示循环)。

需要注意的是,并不是DATA步中的所有语句都是在执行阶段运行,事实上,可以把DATA步语句分为两类:可执行语句(executable)和声明语句(declarative)。
声明语句只在编译阶段起作用,它可以放在DATA步的任何位置。下面是一些基本的DATA步声明语句:
LENGTH:设置内部变量长度
FORMAT:设置变量输出格式
LABEL:设置变量标签
DROP:指示输出文件中删掉哪些变量
KEEP:指示输出文件中包含哪些变量

与声明语句不同,可执行语句在DATA步中顺序很重要。比如从外部读取一个文本文件,我们必须以INFILE语句开始,告诉SAS从哪里读文件;然后输入INPUT语句,告诉SAS怎么读该文件。所以,INFILE语句必须在INPUT语句前面,顺序很重要。

2. DATA步的编译阶段(DATA Step Compilation Phase)

SAS从外部读入原始数据(raw data)时,会在编译阶段开始时创建一个输入缓冲区(input buffer)来存储raw data。如果是从外部直接读入SAS数据(.sas7bdat文件)则不会创建输入缓冲区。SAS在编译阶段还会创建PDV(program data vector),PDV其实就是内存中的一块区域,通过PDV将读入的raw data的每一条数据变成SAS数据集中的每一条观测。在PDV中有两个自动变量,_N_和_ERROR_。_N_=1表示正在创建第一条观测,_N_=2表示正在创建第二条观测,依次类推。_ERROR_只有0和1两个取值,等于0表示在创建当前观测时未发现错误,等于1表示在创建当前观测时发现错误。除了这两个自动变量外,PDV中还有DATA步在创建的数据变量。

假设在我们电脑D盘里有一个student.txt文件,内容如下(第一行红字表示每个字符的所占列位置编号,不是文档内容)

Barbara 61 12D
John 62 175

现在我们用DATA步读入这个文件,并计算每个学生的BMI,看看PDV的工作原理。代码很简单:

data ex1;
infile 'C:\student.txt';
input name $ 1-7 height 9-10 weight 12-14;
BMI = 700*weight/(height*height);
output;
run;
  1. 一开始,PDV中只有_N_,_ERROR_这两个自动变量。
  2. 代码运行到 input name $ 1-7 height 9-10 weight 12-14;时,PDV中会按照input后变量的顺序创建NAME,HEIGHT,WEIGHT三个变量,D表示dropped,K表示kept。只有带K的变量才会output到数据集中。
  3. 代码运行到BMI = 700*weight/(height*height);时,PDV中创建BMI这个变量

在编译阶段,SAS会检查语法是否正确,在编译结束的时候,会创建SAS数据集的内容描述,包括数据集的名字,观测数,变量名,变量数目,变量类型,所有这些内容都可以通过CONTENTS输出。

3. DATA步的执行阶段(DATA Step Execution Phase)

  1. 在执行阶段的开始,自动变量_N_会被初始化1,自动变量_ERROR_被初始化0。一旦INFILE语句识别了我们待读取文件的路径,INPUT语句就会把待读取文件的第一条数据复制到输入缓冲区。
  2. 接着,我们的输入指针(input pointer,下图的红色箭头)会在(@)输入缓冲区的开始处。
  3. 然后,输入指针(红色箭头)会根据input语句定义的方式读入输入缓冲区的这条记录,并移动输入指针,在我们的例子中是将1-7列读入NAME,9-10列读入HEIGHT,12-14列读入WEIGHT,此时输入指针位于第15列。将记录写入到PDV,因为WEIGHT变量类型错误,所以WEIGHT变量值为空(.),同时_ERROR_会变为1,因为WEIGHT为空,所以BMI也为空。
  4. 然后执行OUTPUT语句,将PDV中的这条数据输出到我们的SAS数据集--WORK逻辑库中的ex1。到此student.txt中的第一条数据已读入SAS数据集。
  5. SAS返回到DATA步的第一条语句,也就是data ex1;开始读取student.txt中的第二条数据,此时_N_变为2,_ERROR_重新置为0,其余过程同上。如此往复,直至我们的输入指针遇到EOF(End Of the File),退出循环。DATA步结束。

在我们的这个例子中,如果我们不使用OUTPUT也可以读入该数据,这是因为在DATA步中,当用户没有显式指定OUTPUT时,SAS会隐式调用OUTPUT。不论显式还是隐式output,它们的作用都是讲PDV的那条数据output到我们的SAS数据集中。

参考资料:《Handbook of SAS® DATA Step Programming》

SAS笔记(1) PDV与数据读入的更多相关文章

  1. Keras学习笔记一:修改数据读入方式为本地图片读入

    第一种方法: Keras官方给的图片去噪示例要自动下载mnist数据集并处理,不能修改和加入自己的数据集. from keras.datasets import mnist (x_train, _), ...

  2. R学习笔记(4): 使用外部数据

    来源于:R学习笔记(4): 使用外部数据 博客:心内求法 鉴于内存的非持久性和容量限制,一个有效的数据处理工具必须能够使用外部数据:能够从外部获取大量的数据,也能够将处理结果保存.R中提供了一系列的函 ...

  3. SAS之大话PDV

    SAS之大话PDV 之所以说是数据源,而非输入缓冲区的原因上一条推送已经说明,这里就不再啰嗦啦. 这里我们且将DATA步流程简单地分为从数据源读入到pdv和从pdv写入数据集. IF语句 & ...

  4. SAS笔记

    SAS基础知识 SAS里面的PROC一览 The ACECLUS Procedure : 聚类的协方差矩阵近似估计(approximate covariance estimation for clus ...

  5. R语言数据管理(三):数据读入

    R的数据读入非常灵活,即可以在R软件中直接输入,也可以读入外部数据. 一.直接输入数据 ①c()函数 ②scan()函数 其功能类似c()函数,scan()实际上是一种键盘输入数据函数.当输入scan ...

  6. SAS进阶《深入解析SAS》之Base SAS基础、读取外部数据到SAS数据集

    SAS进阶<深入解析SAS>之Base SAS基础.读取外部数据到SAS数据集 前言:在学习完<SAS编程与商业案例>后,虽然能够接手公司的基本工作,但是为了更深入的SAS学习 ...

  7. OpenSceneGraph 笔记--如何导出三角形数据

    OpenSceneGraph 笔记--如何导出三角形数据 转载:http://blog.csdn.net/pizi0475/article/details/5384389 在OpenSceneGrap ...

  8. IOS开发笔记(4)数据离线缓存与读取

    IOS开发笔记(4)数据离线缓存与读取 分类: IOS学习2012-12-06 16:30 7082人阅读 评论(0) 收藏 举报 iosiOSIOS 方法一:一般将服务器第一次返回的数据保存在沙盒里 ...

  9. Python编程从入门到实践笔记——异常和存储数据

    Python编程从入门到实践笔记——异常和存储数据 #coding=gbk #Python编程从入门到实践笔记——异常和存储数据 #10.3异常 #Python使用被称为异常的特殊对象来管理程序执行期 ...

随机推荐

  1. Hive- 大数据仓库Hive

    什么是 Hive? Hive 是由 FaceBook 开源用于解决少量数据结构化日志的数据统计.Hive是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射成一张表,并提供类SQL查询 ...

  2. 消息队列(Message Queue)基本概念

    背景 之前做日志收集模块时,用到flume.另外也有的方案,集成kafaka来提升系统可扩展性,其中涉及到消息队列当时自己并不清楚为什么要使用消息队列.而在我自己提出的原始日志采集方案中不适用消息队列 ...

  3. 关于IDT报错乱码总结

    可算是把我折腾坏了.一筹莫展.最后才把这些问题搞好.有些事不知道做以前,怎么都想不到.发现了方法之后,原来也不过这样.我觉得自己记性太差.还是好好写下来吧.写下来顺便会帮我重新再梳理一遍.原先乱码是因 ...

  4. 关于MFC的DLL调用方法问题

    参考资料: 一.dll导出方式: MFC的DLL函数导出方法有两种:一种是通过模块定义文件DEF文件:另一种是在导出函数前加_declspec(dllexport). 1.def文件方法: 只需要在E ...

  5. Post提交和Get提交的区别

    表单提交中get和post的区别 1. get: 把表单内各个字段均显示在URL中. post:把表单内各个字段和内容放在html的header内一起传递给action所指的url,用户看不到. 2. ...

  6. G 唐纳德与子串(easy)(华师网络赛---字符串,后缀数组)(丧心病狂的用后缀自动机A了一发Easy)

    Time limit per test: 1.0 seconds Memory limit: 256 megabytes 子串的定义是在一个字符串中连续出现的一段字符.这里,我们使用 s[l…r] 来 ...

  7. IronPython 源码剖析系列(1):IronPython 编译器

    自 IronPython 正式发布以来,由于对 Python 语言的喜爱所驱使,同时我想藉此去了解一下编程语言的编译器,分析器等程序是什么原理,如何运作的,所以我开始了对 IronPython 源代码 ...

  8. rsync 介绍和参数说明

    Rsync 介绍: 我们经常需要在不同目录或者服务器之间做文件同步和更新,Linux提供了很多内置命令可以使用比如scp等等,但是今天我们介绍一个更加强大的工具rsync.rsync 命令是一个远程同 ...

  9. QT4.8.5+qt-vs-addin-1.1.11+VS2010安装配置和QT工程的新建和加载

    1.下载windows下的QT库 QT4.8.5 for vs2010: http://download.qt-project.org/official_releases/qt/4.8/4.8.5/q ...

  10. Python知识点: os.popen

    用例:f = os.popen("%s %s %s" % ("pkg-config", " ".join(args), mod)) pope ...