SAS技术内幕:从程序员到数据科学家
上QQ阅读APP看书,第一时间看更新

第1章 SAS语言入门

SAS是英文Statistical Analysis System的简称,英文发音为/sass/。它具有多层含义:首先,SAS作为一家高科技常青藤软件公司,由参加过阿波罗计划的统计学家James Goodnight博士和John Sall博士成立于1976年,总部位于美国北卡罗来纳州的卡利市。James从1976年7月1日起担任首席执行官至今,在2004年曾被哈佛大学提名为伟大的美国商业领袖。目前,SAS是全球商业分析软件和服务的终极领导者,是商业智能和数据分析行业最大的独立供应商。其次,SAS作为一个庞大的软件系统,以提供“慧识力量”(The Power to Know®)为己任,向全球各行各业提供全面的数据分析技术,涵盖统计分析、趋势预报、预测模型和优化等多个领域。在所有涉及数据分析的领域,SAS公司都有非常强大而严谨的解决方案,是全球主要咨询服务商首屈一指的合作伙伴和分析基础设施提供者。SAS自成立40多年来一直帮助用户和合作伙伴将各种数据转化为知识与智慧,从中发掘企业数据的商业价值。最后,SAS作为一门历久弥新的计算机语言,自1976年起就是专门为数据处理和统计分析而设计的第四代计算机编程语言(4GL)。功能上主要面向数据科学的多个领域,包括数据操作、分析和报告。与传统的通用编程语言不同,SAS是专门为数据科学设计的计算机语言,因此它具有自己独有的语言特征和运行模式。经过40多年的岁月洗礼,SAS语言已经证明自己是数据分析领域的不二之选和事实上的标准。SAS是美国联邦药品和食品管理局FDA接纳和审核电子提交材料以及财富500强生命科学公司的标准统计软件,以严格著称的FDA规定新药临床试验结果的统计分析只能用SAS进行,其他软件的计算结果一律不被承认。

SAS的计算服务包括SAS语言、SAS引擎和数据库服务三大核心模块。其中SAS语言是整个分析服务系统与用户进行交互的接口。

• SAS语言:用于编写SAS程序,主要由如下一系列面向数据操作和分析的语言元素构成。主要包括数据步(DATA Step)和过程步(PROC Step),SAS步是现实世界中处理事情的步骤在程序世界里的反映。

(1)数据步(DATA Step):负责数据读入、数据处理并创建SAS能理解的数据表示,即数据集和数据列。

(2)过程步(PROC Step):负责对数据进行分析,完成各种统计分析功能和图表报表功能。SAS提供400多个功能强大的过程步,用于封装各种分析模块。

(3)SAS宏(SAS Macro):包括宏变量和宏函数,是实现SAS代码重用,减少冗余代码逻辑的顶层利器。宏在很多计算机语言中都已经退化,但在SAS语言中依然保留了极其强大的生命力。

SAS语言是跨平台的编程语言,编写好的SAS程序可以运行在各种架构的Linux、UNIX、Windows甚至IBM大型主机上。SAS运行环境就像Java的JRE或.NET的CLR环境,它提供与主机平台无关的软件执行环境。实际上,SAS公司比SUN更早提出革命性的主机无关的可移植层概念,SAS代码跟Java代码一样“一次编写,随处运行”(Write once, Run anywhere),可跨平台运行在各种操作系统之上,SAS内部至今依然称这种架构为MVA(Multi-Vendor Architecture)架构。

与其他编程语言的I/O系统不同,SAS运行环境提供一个被称为输出交付系统(Output Delivery System, ODS)的部分,用于管理SAS程序的分析结果输出。ODS支持多种高级格式的输出目标(如LISTING、OUTPUT、DOCUMENT)以及多种第三方格式的输出目标(如HTML、PRINTER、MARKUP、RTF等),用户也可以自定义输出模板,来控制分析结果的形态和生成报告的类型,基于同样分析结果可以构建不同形式的报告。

• SAS引擎:为了让SAS语言编程人员专注于数据分析本身,SAS提供一系列引擎来屏蔽数据访问和执行环境相关的细节,让用户仅通过SAS逻辑库引用(Library Reference)就能标记需要分析的数据,而无须将太多的注意力放在具体的数据存储格式、数据库类型以及计算资源的形态等信息上。因此,SAS分析代码变得非常清晰、可重用,分析人员只需关心分析逻辑本身即可。

SAS引擎包括SAS逻辑库引擎(SAS Library Engines)和远程逻辑库服务(Remote Library Services)两大类,分别让用户在SAS代码中可以非常方便地访问本地磁盘上的数据或存储于远程计算机平台(如各种关系型数据库)的数据。根据SAS代码的运行模式,SAS传统上提供一系列运行方式不同的服务器,用于各种计算和分析:

(1)工作区服务器(Workspace Server):SAS代码每次提交到该服务器运行,系统都会新建一个SAS运行环境,它对应操作系统的一个独立执行进程,通常称为SAS会话(SAS Session)。这跟SAS在单机环境上的运行模式大致相同:一个会话对应一个操作系统进程,每个会话具有独立的系统环境和临时数据区。

(2)存储过程服务器(Stored Process Server):SAS代码多次提交到存储过程服务器运行,这些代码会共享一个SAS作为服务启动时建立的那个SAS会话,也就是多次代码提交共享单一会话模式,此时反复提交代码不会新建会话,而是重用已有会话。

(3)连接服务器(SAS/Connect Server):可以让客户端机器充分利用服务端机器上的资源运行SAS程序并处理结果,构建“SAS到SAS”的客户端/服务端运行环境。

(4)网格服务器(Grid Server):它是SAS应用服务器上用于桥接SAS应用和SAS网格环境的逻辑服务器,实现将繁重的计算作业分配到网格环境上并行执行。

• 数据库服务:包括数据访问、库内处理和内存分析几个层次,代表了数据访问模式的几个阶段。

(1)数据访问(Data Access):对于各种各样的数据存在形态和数据库,SAS都提供对应的数据访问服务来保证对特定数据的访问,SAS支持从PC单机文件到关系型数据库、从分布式文件系统HDFS到云端(Cloud)数据的访问能力。

(2)库内处理(In-Database Processing):SAS为改进系统性能,减少数据在数据库管理系统和SAS运行环境之间的“传输和移动”,加速数据分析的开发部署而设计的一种高性能分析平台技术;它采用更加智能化的SQL来增强所选的分析过程步,在一些关键用例上甚至可将SAS系统函数直接部署到数据库运行环境的内部来执行。此时SAS嵌入进程与数据库本身的服务进程构成双头体系结构,共享同一数据。

(3)内存分析(SAS® In-Memory Analytics):随着大数据时代的到来,高级分析和可视化分析呼唤对海量数据的大规模并发访问,海量并行处理(MPP)架构应运而生。SAS运行在分布式计算环境的LASR分析服务器(LASR® Analytics Server)能够预先将海量数据加载到计算机网格的内存,提供安全、无状态的只读操作,从而实现在亚秒级完成对海量数据(亿行级)的分析。

2016年,SAS再次创新性地推出了SAS云分析服务(Cloud Analytics Services, CAS),它是SAS运行在云端最新的数据管理和分析运行环境,可直接对存储在云端(如亚马逊云、阿里云等)的商业数据进行分析处理。同时也是SAS在云平台开放时代的革命性创新,CAS强大的分析服务支持不同的调用接口,用户只要使用Java、Python和Lua等语言API就可直接访问CAS服务,这在SAS历史上是前所未有的开放实践。

SAS网格计算(SAS® Grid Computing)、库内计算(SAS® In-Database)和内存计算(SAS® In-Memory Analytics)是SAS高性能分析平台的三大支柱。近40年来,不管计算环境如何变化,SAS一直致力于将最好的分析技术带给用户,为客户提供从数据(Data)到信息(Information),从知识(Knowledge)到智能(Wishdom)不断演进的“慧识力量”(The Power to Know®)。

数据分析的核心目的就是提升认知的过程。美国系统理论家罗素·艾可夫(Russell L. Ackoff)认为人的心智内容可分为数据、信息、知识、理解及智慧5个层次(图1-1)。其中数据就是承载信息的原始符号,自身除了存在性以外没有任何意义。而信息就是数据通过关系连接在一起具有特定含义的有用数据,能够提供时间(When)、地点(Where)、人物(Who)以及什么(What)之类问题的答案。知识则是按照特定模式组合的信息集合,可以为人们所确定性地记忆和保存,能够回答事情是如何(How)发生之类的问题;然而知识还需要进一步建立在已知(历史)知识基础上对内插和概率性的理解,即从已知知识中获取新知识并综合新知识来回答为何(Why)的过程,才能达到认知和分析性的水准。知识和理解这两个层次就是“记忆”和“明白”的区别,就如小学生会背乘法口诀,但不能够处理两个较大数据的乘法运算一样。智慧则是一个不确定的非概率性外推过程,是建立原理和准则的过程,也是哲学探索的本质;智慧与前四个级别的区别是它不束缚于历史,而是面向未来,即智慧是能够改变“将要发生”事情的知识。不论是商业智能还是人工智能,智慧的建立都离不开DIKW框架和数据分析的阶梯。

图1-1 DIKW模型

下面以SAS的Hello World程序(见程序1-1)开始我们的SAS语言编程之旅。该程序只输出两行文本。SAS与传统编程语言不同,默认它并不输出到操作系统的控制台窗口,而是SAS的日志窗口。

1.1 语言概述

TIOBE指数是用来反映某种编程语言的程度的指标,根据2017年10月最新的数据显示,SAS编程语言占比1.296%,排名第21位,而2016年12月的排名为第22位。编程语言本质上是人类用来与机器沟通,并在人类之间分享思维方法的工具,与它所需要解决的问题领域紧密相关。世界上没有哪一种语言能够解决所有问题,所以尽管计算机领域出现了超过成百上千种编程语言,但终究只有少数强大语言生存下来,SAS便是其中的佼佼者,从1976年创立发展到现在已经40多年。

SAS编程语言入门很快,但要精通需要较长时间,尤其是要掌握通用编程语言里面没有的一些SAS特性则需要花费较长的时间。SAS作为数据分析领域特定的第四代编程语言(Fourth-Generation Programming Language,4GL),与广泛流行的第三代编程语言C++、Java和C#不同,它是专门为数据分析和报告处理中所涉及的复杂数据操作、图形图表制作、文档创建与输出而设计,不拘泥于通用计算机语言规范,而是以用户操纵数据、分析数据为根本导向。

SAS语言总体上是面向过程的计算机语言,有传统编程语言的基本结构。但它不支持面向对象,而是以数据为导向。虽然从SAS 9开始引入若干系统预定义对象:哈希(Hash)、哈希遍历器(HIter)、JavaObj对象和ODSOUT对象,并提供类似面向对象的成员调用语法,但用户至今不能在SAS语言传统的DATA步中创建自定义类;要使用准面向对象的语言结构需要在SAS的第二代DATA(即DS2)步中才可使用。然而,SAS提供强大的互操作能力,用户可在SAS中调用Java对象和Win32 API函数来实现各种复杂功能,也可以在SAS代码中直接调用操作系统的各种命令。

SAS语言中只有两种基本的数据类型:字符型和数值型,分别映射统计学中的定性数据和定量数据。在统计学的世界里,数据分析者并不关心数据的存储细节,而是关心数据的语义表达。从外部数据到SAS系统内部的数据存储表达之间,用户可以使用输入格式(INFORMAT)和输出格式(FORMAT)对数据进行读和写的格式化转换。

SAS在一些过程中为这两种基本数据类型提供更丰富的数据类型支持,如从SAS9.1开始引入的函数编译过程步(PROC FCMP)提供类似C语言的结构体支持,而矩阵运算过程步PROC IML提供矩阵概念和专业运算。但总的说来SAS与通用编程语言所支持各种面向存储的基本数据类型:如布尔类型、整数类型、浮点类型和字符类型不同,它更关心的是统计学上的数据类型。

根据测量尺度划分,统计学上的数据类型只有定类(如性别)、定序(如年级)、定距(如摄氏温度)和定比(如重量)4种基本数据类型,每种数据类型内所包含的信息量或熵值是不同的,因而适用的统计分析方法也就不同。

SAS语言提供非常强大SAS宏语言预处理器,可实现SAS程序编译前的宏替换功能。这一特性允许SAS程序在编译和运行期间,动态改变程序代码自身,甚至可实现宏本身的递归调用。使用SAS语言的统计分析人员时常惊叹于SAS宏语言的强大功能,而一些不那么熟悉SAS宏语言的编程人员则时常为它与传统计算机编程语言的不同而困惑不解,以至于时常迷失在SAS宏与非宏的程序世界里。

SAS语言是一门比较复杂的计算机语言,它到底是编译执行还是解释执行有时候连有经验的SAS开发人员也会感到困惑。鉴于SAS语言包含灵活的语言元素,SAS代码中的Macro宏是由宏解释器展开的,但非宏的DATA步和PROC步则以步(Step)为单位由SAS依次进行编译执行。SAS并不是逐句解释执行,而是按步编译执行。DATA Step中包括的语句也分为编译阶段起作用的声明性(Declarative)语句和运行时起作用的可执行(Executable)语句两类。SAS语言是兼具编译和解释的混合型计算机语言,鉴于此,维基百科的分类也很难处理是将SAS语言归入编译型语言(Compiled Language)还是解释型语言(Interpreted Language)。

SAS语言最强大的能力是为分析编程人员提供了完备细致的数据访问,而不用太多考虑数据存储的格式和存储位置等细节,如DATA步和PROC SQL过程步就提供了各种各样的数据操作能力,而丰富的PROC步支持让分析人员专注于数据分析本身和参数设定。用户通常无须为各种标准化的严谨分析任务重新编写代码逻辑,SAS已经为各种分析方法规范化了统一的形式和统计量,一旦SAS编程入门,通常只有不懂的统计方法和类型而没有不会使用的PROC步。

从传统的编程语言转换为SAS编程语言进行编程,首先要谨记如下一些SAS语言的核心规则。

(1)SAS程序由一系列SAS语句组成,所有的语句都以分号“;”结束。SAS代码中可以嵌入待分析的数据行,但数据行不是SAS语句,因此它不需要以分号结尾。

(2)一个SAS语句可以跨多行编写,多个SAS语句也可以放在同一行上。SAS语句可以从一行中的任意位置开始,代码缩进并非必需的。

(3)SAS语句中的关键字以空格分隔的,通常由“关键字”或“关键字=参数”系列组成。某些语句在必选和可选选项之间会用斜杠“/”号进行分隔。

(4)SAS语言元素不区分大小写,用户可以使用大写、小写以及它们的混合。但当字符串作为字符变量的数据时则区分大小写,如“Hello World”和“HELLO WORLD”是两个不同的字符串值。

(5)SAS代码中标识符长度较短,用来标识数据库和外部文件的逻辑库引用(libref)和文件引用(fileref)名称最长不得超过8字节长度,而数据集(数据表)名称和变量(数据列)名称最长不得超过32字节长度。

(6)SAS提供强大的SAS宏系统支持,含有百分号“%”或连字符“&”的代码文本会在编译前触发SAS宏展开。SAS提供语言级别的宏支持,而不仅仅是简单的宏替换,它包括宏变量、宏函数、宏分支以及宏循环等完备流程控制。

总体上,SAS程序主要由一系列的全局语句和SAS步构成,包括DATA步和PROC步。而所谓的SAS步则由一系列的SAS语句(Statements)构成。每一个SAS步都有开始和结束边界,SAS根据步的边界进行独立编译和执行。图1-2展示了SAS代码的宏观构成。

图1-2 SAS代码的宏观构成

SAS步由DATA或PROC语句开始,默认结束于下一个DATA或PROC步的开始处。用户也可用RUN语句显式地标识DATA或PROC步的结束并提交执行之前的SAS代码。对于某些资源依赖型PROC语句,则通常需要以QUIT语句来提交当前PROC步并释放资源返回SAS会话中。比如PROC SQL、PROC CAS等过程步,这种过程步可包含多个RUN语句,但只有在遇到QUIT语句时SAS才释放系统资源返回当前SAS会话。

• 全局语句:在DATA步或PROC步之外,SAS还包括若干全局语句,通常用于指定全局选项或者其他全局性的功能。比如TITLE语句就可用来指定后续PROC步输出报告的标题文字,其中TITLE#(#为数字,如TITLE2)全局语句可用来指定特定级别的标题,最多可达11级。如果希望在输出的图表中关闭特定级别的报表标题,用户可以无参数调用TITLE语句来实现。比如程序1-2可设置报表输出的标题。

     程序1-2 全局语句
     title "The title of my first report"; /*设置输出报告的标题*/
     title2 "Author:Yinliang Wu"; /*设置第二级的报告标题*/
     title; /*关闭报告标题*/

各种SAS选项语句也属于全局语句,功能上类似于操作系统的环境变量,不过它用来指定当前SAS会话有关的系统设置,如程序1-3用于设置当前会话(Session)的语言区域属性(Locale)为英文,此时后续的过程步都会受此选项影响输出英文语言的报告。

• DATA步:数据步负责为后续数据步或过程步准备待分析的数据,它是SAS语言核心的组成部分之一。其基本语法为

比如程序1-4创建一行具有5列的数据表,其中Name和Sex是字符型变量,其他3个为数值型变量。它与系统数据集sashelp.class的表结构类似。

• PROC步:SAS过程步是执行特定任务的一系列SAS语句的集合,它以PROC语句开始,一般到下一个RUN语句结束;如前所述,某些PROC如PROC SQL允许有多条RUN语句提交代码到DBMS内执行,但只有当该PROC最后一个QUIT语句运行后才会释放资源返回SAS会话环境。每个过程步都有自己特定的SAS语句,也有很多过程步共享相同的SAS语句和参数选项,如几乎所有的过程步都有data=参数用来指定待处理的输入数据集名称(见程序1-5)。

参数data=mydata是proc contents和proc print两个过程步语句都有的选项,用来指定过程步的输入数据集。如果过程步没有指定data=参数,则系统默认使用当前SAS会话中最后使用或生成的那个数据集,该数据集的名称也存在于当前会话的系统宏变量&SYSLAST。

• 程序注释:代码注释通常用于标注不可执行的文本,如描述程序的功能,或出于生成文档的目的在代码中添加说明性文本。注释还可用来在调试代码过程中将已经调试好的SAS代码暂时隔离,当代码运行时注释中的代码会被编译器自动忽略,但SAS注释依然会被写入SAS日志文件。鉴于SAS宏本质是文本替换,需要特别注意的一点是在MACRO宏代码中应尽量使用块注释,谨慎使用行注释以免导致不期望的宏展开,宏代码中使用行注释应中以%*开始,分号结束。SAS块注释和行注释如下。

(1)块注释:SAS语言支持C/C++和Java等语言广泛使用的块注释,它以/*开始,以后续最近的*/号结束,注释可以包含分号以及任何长度的文本,也可以跨行(见程序1-6)。但SAS代码不支持嵌套使用块注释。

(2)行注释:行注释以星号“*”开始,结束于最近的一个分号“;”处。虽然它可注释多行文本,但它总是以最近的一个分号(包括引号中的分号)结束;其设计初衷用于调试过程中注释掉单行语句,跨多行的文本建议使用块注释以免产生意想不到的结果。(见程序1-7)。

虽然SAS代码在格式上具有很强的灵活性,但良好的代码风格能提高代码的可读性和可维护性。因此,一般情况下请遵循如下SAS代码格式化规范,使SAS代码具有较强的可读性。

(1)全局语句、DATA/PROC步语句、步结束语句RUN/QUIT等语句应开始于第一列,而其他子语句通常采用逐级缩进,以显示层次结构关系。

(2)SAS步与步之间通常用空行分隔,以表示SAS代码的编译边界,方便代码错误调试。

(3)当单行代码因参数较多导致长度较大时,应折行处理,并在该语句的结束分号后加上一个空行。

总的来说,SAS的DATA步和PROC步是SAS语言对数据分析工作的精妙抽象和完美封装,数据步主要解决待分析的数据结构和数据准备问题,而过程步解决特定分析方法和流程的实现和封装;这两种SAS步就像数据结构和算法设计,大体上分别负责数据结构和算法逻辑实现。只有当需要更加复杂的自定义数据处理和分析算法时,才需要后面章节中将会讲到的各种函数封装进行扩展。

1.2 编程环境

SAS编程需要使用什么样的开发环境?其实它跟其他计算机语言一样,可用任何纯文本编辑器编写SAS代码,如Windows平台的记事本,NotePad++或者UltraEditor工具。也可以使用UNIX上的vi来编辑代码,不过需要注意的是Windows平台使用回车换行符CRLF而Unix平台使用换行符LF进行文本换行。用文本编辑器生成的SAS代码文件,其文件编码(File Encoding)需要与SAS运行时的会话编码(Session Encoding)匹配,否则可能出现不期望的乱码或程序行为。这并不是SAS语言编程特定的文件处理问题,而是所有编程语言都会面临的源代码文件编码和编译器读取文件的所采用的编码之间的匹配问题。

在SAS执行环境中检查当前SAS会话编码,可使用PROC OPTIONS过程步检查(见程序1-8),它会输出当前SAS系统使用的默认语言区域设置以及字符集编码信息。

对于用户用文本编辑器编写好的SAS代码,如何用命令行方式编译运行SAS代码?对于已经安装好SAS环境的机器,用户只需要调用sas.exe然后指定-sysin命令行参数将SAS代码文件的全路径传递给SAS即可。默认SAS代码运行后生成的日志文件会输出到当前路径,用户也可以使用命令行参数-log进行指定。比如:

     C:\>"C:\Program Files\SASHome\SASFoundation\9.4\sas.exe"
         -sysin C:\temp\helloworld.sas -log C:\temp\helloworld.log

SAS默认使用配置文件为C:\Program Files\SASHome\SASFoundation\9.4\sasv9.cfg,也就是当前机器上安装SAS时生成的默认配置。检查该文件的内容可发现它默认指向了SAS安装目录下面的某个语言特定的配置文件。比如在中文环境上安装的SAS,该sasv9.cfg文件的内容如下,表示默认使用中文配置来建立SAS会话环境并运行SAS代码。

如果用户想在中文的环境上运行特定配置的SAS,如希望用纯英文版SAS执行用户代码,用户只需要在运行SAS代码时直接指定特定配置文件即可。检查该环境运行的SAS日志文件将会发现所有的输出内容变成了英文文本。

同理,如果想用英文版SAS执行代码但程序中又要支持处理中文数据,用户则可以使用SAS安装目录中的nls\1d\sasv9.cfg配置文件;如果想用Unicode版本的SAS来运行代码,则需要使用nls\u8\sasv9.cfg配置文件。

图形用户界面

由于SAS被设计用于数据分析,因此更常见的情况是利用图形用户界面(GUI)来编写SAS代码并调试运行。只有开发完毕后才用上面提到的命令行方式包装到后台静默执行或者作为操作系统服务运行。到目前为止开发SAS程序,通常在如下4种环境之一进行。

(1)Base SAS运行环境:在机器上单独安装SAS Foundation软件,然后在SAS图形界面中进行编程。这是SAS最传统和最常见的SAS编程环境。

(2)SAS Enterprise Guide(简称EG)Windows客户端环境:它是运行在Windows平台比Base SAS更高级的SAS企业客户端。用户即使不熟悉SAS编程语言,也能够用鼠标拖拽的方式利用EG快速进行可视化编程。EG是独立于SAS运行环境的一个客户端产品,它需要调用本地安装的Base SAS运行环境,或者连接到远程安装的SAS环境来执行生成的SAS代码,远程的SAS环境可以是SAS Workspace Server或SAS Stored Process Server服务器,EG客户端使用SAS Integration Technologies的集成对象模型(IOM)与后台进行通信。

(3)SAS Studio浏览器客户端环境:它是基于浏览器的Web客户端,让用户可以在本机不安装SAS和Enteprise Guide等客户端的情况下进行SAS编程。SAS Studio中提交的代码通过SAS互联网基础设施平台(WIP)或Viya组件运行在远程服务器上,远程服务器处理完毕,结果会返回并显示在SAS Studio浏览器窗口。SAS Studio产品使SAS编程环境可以部署在云端,而客户端可实现零安装部署就能进行SAS编程和调试。比如,SAS为学术界免费提供的云服务SODA,用户只需注册即可实现随时随地进行SAS编程和调试。

(4)SAS University Edition虚拟机环境:即所谓的SAS大学版,实际上它是SAS免费提供的虚拟机版本,其中不仅包括SAS Studio和Base SAS基本环境模块,还包括SAS/STAT、SAS/IML、SAS/ETS和SAS/ACCESS Interface to PC File等组件,主要用于SAS编程的学习培训。用户只需要从SAS官网https://www.sas.com/zh_cn/software/university-edition.html下载虚拟机即可。另外,用户也可以在亚马逊AWS网站上创建亚马逊账号,然后在“Marketplace”中输入“SAS University Edition”找到SAS大学版,随后按照提示启动编程界面。亚马逊的AWSMarketplace网址为https://aws.amazon.com/marketplace。

由于数据分析系统的特殊性,SAS编程环境界面大体包含以下几个基本窗口:

• 编写/提交SAS代码的[程序]窗口或[代码]窗口;

• 查看SAS代码运行细节的[日志]窗口;

• 显示输出结果的[输出]窗口。

比如在Base SAS的代码窗口中输入前面的HelloWorld程序,点击菜单[运行(R)]→[提交(S)]就可看到程序运行结果,用户也可以直接点击工具栏上的运行按钮,或直接按F3快捷键提交代码运行,这样就可在日志窗口中看到提交代码的执行细节和结果。

• Base SAS环境(见图1-3)。

图1-3 Base SAS环境

• SAS Enterprise Guide环境(见图1-4)。

图1-4 SAS Enterprise Guide环境

• SAS Studio环境(见图1-5)。

图1-5 SAS Studio环境

当SAS代码提交编译运行时,SAS会自动检查语法错误,如果发现语法错误,错误信息会输出到SAS日志窗口。语句中常见语法错误包括关键字拼写错误、无效选项、引号不匹配,以及语句结束符分号缺失等问题。

SAS语法错误分为ERROR和WARNING两大类,分别以红色和绿色显示。红色的信息包括错误所在的行和列,以及对错误的详细描述;红色的错误需要用户仔细检查并加以修正,而绿色警告不妨碍后续程序的运行。

由于SAS编译器具有强大的拼写错误容错能力,它能够智能修正的错误被归入WARNING类,代码依然能正常运行。而红色表示SAS未能修正的错误,用户必须修正后才能正常执行。比如程序1-9示例代码依然能正常运行,尽管PROC PRINT DATA等几个关键字都被拼写错了(多了个X),其仍能输出如图1-6所示结果。

图1-6 语法容错能力

对于一些参数错误,如指定了不存在的数据集sashelp.classx,SAS则会报告ERROR错误。

     59  proc print data=sashelp.classx;
     ERROR:文件"SASHELP.CLASSX.DATA"不存在。
     60  run;

很多时候正是因为SAS运行环境对代码的容错能力太强,一些错误会隐藏得较深,不能被用户立即发现。因此用户可采用分块调试的办法将语法错误限制在最小的范围内。比如下面一行代码,SAS在第三次提交的时候才会报告错误。

     title "Hello World;

SAS程序主要由数据步(DATA Step)和过程步(PROC Step)组成,SAS编译器会按步编译运行。如果没有语法错误则会启动编译与执行,重复这个过程直到所有的SAS程序“步”被处理完毕。

当代码编辑窗口被激活时用户可以随时点击菜单[文件(F)]→[保存(S)]来保存你的代码。SAS使用默认文件编码保存程序,如在中文SAS环境上默认使用的是Simplified Chinese(EUC)编码。用户也可以在保存代码对话框中指定Unicode UTF-8、Unicode(UTF-16LE)或Unicode(UTF-16BE)编码格式进行保存,同时也可指定是否输出字节顺序标记(Byte Order Mark, BOM)进行存储。

字节顺序标记BOM就是用于告诉文件处理程序在读取文件内容时,该目标文件的正确编码。BOM约定对进制文件最开始的2字节或3字节进行特殊处理,如果某个文件的前3个字节为十六进制值的EF BB BF,则表明该文件为UTF-8有BOM的编码格式文件;如果前2个字节的十六进制为FF FE或FE FF,则分别表示文件为UTF-16 Little Endian或UTF-16 Big Endian编码格式。

对于Hello World程序,你可能会有疑问——为什么有输出窗口却没有任何输出信息?SAS程序的输入输出与传统编程语言的文件I/O不同,SAS的输出窗口是给前面提到的SAS ODS输出交付系统的LISTING目标使用的。由于Hello World程序没有任何ODS输出,只调用了PUT语句输出日志,因此输出窗口没有结果。程序1-10尝试创建一个SAS数据集,然后将该数据集打印到输出窗口。

提交代码执行后,SAS首先创建数据集WORK.MYDATA,WORK是SAS运行默认的SAS逻辑库。在输出窗口(见图1-7)SAS会打印出用户生成的数据集WORK.MYDATA。

图1-7 WORK.MYDATA内容

需要查看SAS数据集的数据结构和定义时,可以使用PROC CONTENTS过程步进行查看。

执行结果将显示在输出窗口(见图1-8)。可以看到数据集编码为“euc-cn Simplified Chinese(EUC)”,数据表示法为Windows_64,表示数据是在Windows 64位的平台上生成。在与引擎/主机相关的信息中,文件名是数据集在磁盘上的存储路径。最后一节则是数据集中所有变量的类型和长度,可以看到包括数值和字符两种类型,数值的默认长度为8字节。

图1-8 数据集的元数据信息

Base SAS需要在单机环境或者服务器环境下单独安装,下一节将展示如何实现不安装任何SAS运行环境,就可在Web浏览器中随时随地编写自己的SAS代码。

1.3 SAS Studio编程

SAS软件具有巨大的商业价值,一般的人很难获得最新的安装拷贝。读者该如何学习SAS编程呢?SAS考虑到全球不断增长的数据分析需求以及体现对学术研究领域的一贯支持,SAS提供基于SAS私有云的SAS Studio应用服务SODA。

SODA全称SAS® OnDemand for Academics是SAS为学术群体提供的免费在线应用服务环境。运行在SODA上的SAS Studio可以让你在任何时间、任何地点编写/运行自己的SAS分析代码,而且所有用到的数据和代码都会存储在SAS私有云。这是目前除了在本地安装强大的SAS系统外,学习使用SAS程序开发成本最低和最快捷的方式,用户只需要一个电子邮箱账号和浏览器即可。

(1)在浏览器中输入网址https://odamid.oda.sas.com/SAS ODARegistration访问SAS® OnDemand for Academics(见图1-9),按要求提交必要信息注册SODA账号,你的邮箱将会收到用户ID,该用户ID将会在后面用来登录SODA控制中心来使用SODA提供的应用服务。

图1-9 注册SODA账号界面

(2)注册完成后,通过网址https://odamid.oda.sas.com访问SODA控制中心。注册完成后,用户并不能马上收到注册信息,需要耐心地等待一段时间。登录SODA控制中心时,需要使用邮件中收到的【用户ID】和【用户密码】,其中【用户ID】并不是邮箱地址yinliangwu@gmail.com,而是SODA分配的用户ID,如yinliangwu0。SODA登录界面如图1-10所示。

图1-10 登录SODA界面

登录后,系统将引导用户到SAS ODA的控制中心(见图1-11)。页面上用户会看到一个SAS® Studio应用,点击它即可启动SAS® Studio应用。

图1-11 SODA面板

用户也可在登录SAS ODA控制中心后,直接在浏览器中输入如下网址访问SAS Studio应用https://odamid.oda.sas.com/SAS Studio。目前在SODA上提供服务的SAS Studio为3.5企业版,它支持Chrome 27+、IE9/IE11、Firefox 21+和Apple Safari 6.0+以上版本的浏览器。后台SAS服务器为Linux 64位版本的SAS、SAS Studio为用户提供了一个编写和远程执行SAS程序的高效Web开发环境。

(3)SAS Studio主界面包括顶部的菜单栏、左侧的导航面板和右侧的内容窗口(见图1-12)。导航面板包括“服务器文件和文件夹”“任务和实用程序”“代码段”“逻辑库”“文件快捷方式”和“SAS文件夹”等模块。其中“服务器文件和文件夹”和“逻辑库”比较常用,“服务器文件和文件夹”是用户在云端服务器上的磁盘存储空间,一般映射到用户特定的主目录/home/<userid>,如/home/yinliangwu0。

图1-12 SAS Studio主界面

右侧提供了程序窗口(见图1-13),包括“代码”“日志”和“结果”3个窗口。一般步骤是在代码窗口中输入SAS程序,然后点击代码页签工具栏最左边的运行按钮,或者直接按F3功能键直接执行代码。比如:

图1-13 SAS Studio程序窗口

执行日志可以查看SAS Studio日志窗口(见图1-14),包括提交的源代码信息。

图1-14 SAS Studio日志窗口

结果窗口是用来输出ODS结果的,用户可以在程序中输入如下代码,然后按F3功能键运行SAS代码即可看到ODS输出结果。在SAS中一般PROC步会将分析的结果输出到ODS目标(见图1-15)。

图1-15 SAS Studio结果窗口

在分析中用户需要上传自己的数据文件,可以点击左侧导航面板中的“文件(主目录)”,然后在菜单中选择“上载文件……”(见图1-16)。

图1-16 上载文件到主目录

在弹出对话框(见图1-17)中单击“选择文件”,然后选择本地计算机上的数据文件上传到远程服务器,如C:\temp\class.csv。

图1-17 “上载文件”对话框

上传完毕在左侧的导航面板“文件(主目录)”中将出现class.csv文件,表明该文件已经上传到云端。如果要将该csv数据导入SAS系统,用户可以双击它,SAS Studio会自动生成导入数据所需的SAS Code,用户也可以选择不同的参数进行数据导入。

云端的SAS环境为了让全球所有用户都能使用、支持所有语言和国家地区的用户,其默认数据文件被设置为UTF-8编码。但在中文Windows环境下SAS生成的文本文件默认是GB2312/GBK编码,用户可以使用记事本的“另存为”功能,将文件转存为UTF-8编码格式即可完成转码工作。比如,如果用户上传一个本地Windows导出的csv文件,而在SAS导入的时候会默认上传的文件是UTF-8编码格式,此时就会出现乱码。解决方法如下所述。

(1)使用记事本或其他文本工具(如Notepad++或Ultra Editor)将数据文件打开,然后使用“另存为”,选择UTF-8编码保存即可进行转码。

(2)用户也可在数据导入的SAS代码中明确指定待输入文件的正确编码方式,由SAS Proc Import进行编码转换,将数据正确导入SAS数据集,其默认编码为UTF-8。

如果用户上传的是使用Windows导出的csv文件,用户需要在将该文件导入时明确指定该输入文件为GB2312编码,步骤如下:双击class.csv,然后在右侧class页签下点击“编辑”,SAS Studio会自动生成对应的SAS代码“程序2”(见图1-18),修改FILENAME语句如下,运行即可正确导入数据。

图1-18 设置导入数据的文件编码

在结果窗口中可以看到导入完毕的数据,如WORK.IMPORT1。在缺省情况下输出数据都会放到临时逻辑库WORK。此时调用PROC CONTENTS输出的数据集的元数据信息如图1-19所示。

图1-19 数据集的元数据信息

调用PROC PRINT打印数据集内容信息如图1-20所示。

用户可以通过鼠标右键点击左侧导航栏下的“逻辑库/我的逻辑库/WORK/IMPORT1”来更改数据集名称,如改为WORK.CLASS(见图1-21)。

图1-20 数据集的数据内容

图1-21 更改数据集名称

这样,用户就可以在本次SAS会话期间,即在本次登录SAS Studio直到关闭浏览器退出SAS Studio应用期间一直使用WORK.CLASS数据集,修改代码如下,即可查看导入的数据(见图1-22)。

运行代码用户将看到打印的数据变为刚上传后导入的那个数据集WORK.CLASS。

用户也可将自己的SAS源代码保存到云端的服务器,如用户选择保存到“文件(主目录)”,文件名为PrintClass.sas即可(见图1-23)。

保存到服务器上的文件/home/yinliangwu0/PrintClass.sas,从窗口下方的状态栏中可以看到路径(见图1-24)。

图1-22 引用临时数据集

图1-23 保存SAS源代码到服务器

图1-24 SAS源代码在服务器上的路径

由于WORK是临时逻辑库,在当前SAS会话结束时系统会自动删除。如果用户想要在服务器磁盘上永久保存该临时导入的数据集WORK.CLASS,可以在导入之前指定一个非临时逻辑库来保存数据。用户也可以在SAS代码中新建一个非临时逻辑库mylib,然后在mylib中生成一份WORK.CLASS的复制。

这样用户就可以将打印class数据集的代码改为(见图1-25):

图1-25 在服务器上生成永久性数据集

运行上面的代码后,用户可以看到服务器的“逻辑库/我的逻辑库”多了MYLIB逻辑库,其中包括数据集CLASS。即使用户关闭SAS Studio,这个数据集也会一直存储在服务器磁盘上。这样当用户下一次登录SAS Studio时可以继续使用该数据集(见图1-26)。

图1-26 永久性逻辑库MYLIB中的数据

该数据集对应的物理文件位置就是远程服务器odaomr.oda.sas.com的磁盘路径/home/yinliangwu0/class.sas7bdat(见图1-27)。

图1-27 永久性逻辑库路径的数据文件

至此,用户就完成了数据集的上传,并将数据保存在非临时逻辑库mylib。同时也在服务器上也编写了SAS程序/home/yinliangwu0/PrintClass.sas。这样我们就可以随时退出SAS Studio环境。退出SAS Studio应用只需点击右上角的“注销”菜单即可(见图1-28)。

图1-28 注销SAS Studio

安全退出后显示如下页面,应关闭浏览器清除客户端数据以提高安全性(见图1-29)。

图1-29 已安全注销窗口

由于所有数据都保存在云端,因此用户下次登录时所有的数据和程序都还在(见图1-30),用户可以随时继续自己的分析工作,也可以随时保存工作并退出。

图1-30 服务器文件和文件夹

关于云端的SAS Studio环境,以下重要提示信息可用于检查版本或者设置系统选项。

(1)检查SAS Studio和后台SAS系统的版本信息:点击右上角“?”号,然后选择“关于SAS® Studio”即可查看(见图1-31)。

图1-31 检查SAS Studio和后台SAS版本号

(2)查看系统默认的文本编码:单击右上角“其他应用程序选项”按钮,选择“参数选择→常规→默认文件编码:UTF-8”,该选项设定读取和保存SAS程序代码的默认编码格式(见图1-32)。

在中文平台上创建的SAS程序文件默认是GB2312编码。而SAS SODA系统默认采用UTF-8处理文件读写和数据,因此建议在上传文件/上传代码之前确保文件为UTF-8编码。该选项并不影响前面提到的数据导入功能,因此即使修改此文本编码为GB2312,也不会修正从客户端上传GB2312编码的数据文件导入SAS系统环境,更不会有文件编码GB2312和系统默认会话编码UTF-8不一致而导致的乱码问题。

图1-32 SAS Studio参数选择窗口(常规)

(3)在参数选择窗口“启用提示”可以改善程序编辑器的行为,从而让用户在进行SAS编程的时候获得必要的上下文提示信息(见图1-33)。

图1-33 SAS Studio参数选择窗口(编辑器)

启用选项后SAS Studio编辑器能动态提示帮助信息(见图1-34)。

图1-34 SAS Studio动态提示信息

(4)在SAS Studio中利用“代码段”可以方便让用户重用某些代码片段。比如我们可以在代码编辑窗口中任意选中某些代码(见图1-35),然后单击工具栏“添加至我的代码段”按钮,即可命名特定代码片段。

图1-35 SAS Studio添加代码片段

这样用户在新建另一个SAS程序时就可以很方便地在程序编辑器中通过双击左侧的代码片段(见图1-36)将它添加到当前光标处。

图1-36 SAS Studio我的代码段

比如下面编写的一个简单的显示MYLIB.CLASS平均值等简单统计量信息的程序(见程序1-11)。

运行我们的代码然后保存到MeansClass.sas。当我们需要插入DisplayLogo信息时,只需要将光标定位到特定位置,然后双击左侧的代码段即可实现自动代码插入(见图1-37)。

图1-37 SAS Studio插入代码片段

(5)创建自动执行代码:SAS支持在系统启动时自动执行某些程序。比如我们希望保存在磁盘特定目录中的数据文件,在每次登录SAS工作环境时都可以用于分析,此时我们可将libname语句指向它所在目录,并加入Autoexec.sas文件中即可(见图1-38)。

图1-38 SAS Studio自动执行代码(Autoexec.sas)

相应的原代码中libname mylib “/home/yinliangwu0”;语句就可注释掉或删除。SAS中的autoexec.sas文件是SAS会话启动时系统自动执行的代码段。对于SODA上的SAS Studio用户,该sas文件在用户每次登录SAS Studio时都会自动执行。因此,/home/yinliangwu0路径中的数据集都会默认出现在mylib逻辑库中,供后续分析处理用。