简介:《小白学SAS基础教程》面向零基础的数据分析初学者和希望提升数据管理效率的职场人士,采用对话体跟随主人公“小白”的学习路径,降低SAS命令与语法带来的入门门槛。压缩包共1个PDF文件,大小约1.76MB,适合在电脑或移动端随时阅读。已有709人学习,反映出该教程对SAS新手具有持续吸引力。内容围绕数据整理、作图和制表展开,重点讲解数据集建立、常用函数运用、缺失值与异常值等数据清洗思路,以及利用SAS绘制常规图形、生成规范报表的方法;不只罗列命令,更强调操作背后的实际用途与问题解决逻辑,并配有可参考的程序和案例。读者可借此建立从数据准备到结果呈现的完整入门框架,形成可迁移到实际工作中的SAS应用能力,适合作为系统自学与案头查阅的基础读物。
1. 先搞懂一件事:SAS 到底是什么,零基础能不能学
很多人搜 SAS 基础入门,第一眼撞上的是“数据步”“程序步”“proc 过程”“逻辑库”这一串词,第二眼就把页面关了。把包装拆掉看,SAS 其实是一条处理数据的流水线:把散在表格和数据库里的数据装进来,洗干净,算出你要的指标,画成图,排成能直接交上去的报表。《小白学SAS基础教程》带你走的,就是这条流水线最前面、也最关键的一段。
它适合每天跟成百上千行数据打交道的人:要做月度报表、要做数据核查、要反复算同一批指标,却不想每次都手工复制粘贴。零基础不是障碍,真正卡住新手的是那些没解释就甩出来的术语。
2. 打开软件别慌:三个窗口就是你每天的全部工作台
第一次打开 SAS,界面会让人有点懵:左边一列树状目录,右边一大片空白,上面还有一排菜单。别急着记菜单,绝大多数人 90% 的时间只跟三个窗口打交道,剩下那些按钮一年也点不了几次。
新手最容易犯的错,是把 SAS 当成 Excel 那样“点点点”的软件。它确实有菜单,也能导入导出,但真正干活的方式是:在编辑器里写几行程序,提交运行,然后去日志和输出里看结果。把这个循环跑顺,后面所有内容都只是往这个循环里加东西。
2.1 编辑器写、日志看、输出读:一次完整的运行循环
三个窗口的分工非常清楚:
- 编辑器:你写程序的地方,所有代码敲在这里。
- 日志:程序运行过程的记录本。跑成功会写“NOTE: 数据集 XXX 有 N 个观测”,跑失败会写“ERROR”,并且告诉你哪一行出了问题。
- 输出:结果的展示区。算出来的均值、画出来的图、生成的表,都先落在这里。
写一段最简的程序感受一下。打开编辑器,敲下面这几行:
/* 第一步:把三条记录读进一个叫 demo 的数据集 */ data demo; input name $ score; /* name 后面的 $ 表示这是字符型变量 */ cards; /* cards 告诉 SAS:下面是数据 */ A 88 B 92 C 75 ; /* 这个分号必须单独占一行,表示数据结束 */ run; /* run 表示这一段程序写完了,可以执行 */点工具栏上那个跑步的小人图标,或者按执行键,程序就提交了。这段代码里,data demo;是给数据集起名字,input是声明有哪些变量、什么类型,cards;之后紧跟的几行就是真正的数据,最后一个单独的分号告诉 SAS“数据到此为止”,run;收尾。第一次写不用理解全部,先记住这个结构就行。
跑完之后,去日志窗口看。如果只有一堆 NOTE,说明成功;如果出现红色的 ERROR,说明有问题,具体哪一行、什么原因,日志里都写着。这个习惯请从第一天就养成:先看日志,再看输出。新手十次报错里有九次,日志已经把答案写得很清楚了。
输出窗口里会出现一个简单的汇总。如果你还想对分数算个平均,再补一段:
/* 第二步:对 demo 里的 score 求平均 */ proc means data=demo mean; var score; /* var 指定要分析的变量 */ run;proc means是一个现成的“过程”,data=demo指明对哪个数据集动手,mean是要输出的统计量关键字,var score;说明只算 score 这一列。这类以proc开头的东西,SAS 里叫程序步,后面会反复用到:proc sort排序、proc sgplot画图、proc tabulate制表,都是同一个套路。
到这儿你已经跑通了第一个循环:写 → 提交 → 看日志 → 看输出。这就是 SAS 的日常。
2.2 数据步和程序步:所有 SAS 程序都是“两段式”骨架
再回头看上面那两段代码,你会发现一个规律:第一段以data开头,第二段以proc开头。SAS 的程序结构就是这么简单,只有两种步:
| 类型 | 开头关键字 | 干什么 | 典型语句 |
|---|---|---|---|
| 数据步 | data | 造数据、改数据、洗数据 | data、input、cards、set、merge |
| 程序步 | proc | 对数据做分析、出图、出表 | proc means、proc sort、proc sgplot |
数据步解决的是“数据从哪来、长什么样”的问题。它最少要三句话:data起名、input定义变量、cards引进数据。只要数据已经在 SAS 里了,你想加一列、改一列、筛一批记录,也都是靠数据步完成的。
程序步解决的是“算点什么、展示点什么”的问题。它的写法更统一:proc 过程名 data=数据集名 选项;,然后跟一两句说明语句,最后run;。
颜色在这里帮了大忙。编辑器里蓝色的是 SAS 的固定语法,一个字都不能改,比如cards、run、proc;浅蓝色的是过程内部的语句,比如class、var;黑色的是你自己起的名字,比如demo、score,随便你改。要是哪句写错了,它会变红,一眼就能发现。这个小设计对零基础的人特别友好,等于软件在替你标错。
有一点要提前说清楚:run;不是可有可无的装饰。它告诉 SAS“这段程序写完了,开始执行”。很多人写完忘了加,程序就卡在那儿一动不动,还以为软件坏了。
2.3 逻辑库与 Work:为什么你的数据集一关软件就没了
现在回答一个新手最常见的疑问:我辛苦建好的数据集,怎么第二天打开全不见了?
看左边的资源管理器,展开“逻辑库”,会看到几个文件夹:Work、Sashelp、Maps 之类。Sashelp装的是自带的示例和帮助数据,Maps装的是地图数据,而Work是留给你用的。
问题就出在 Work 上:它是临时逻辑库,SAS 一关闭,里面的东西自动清空。你用data demo;建的数据集,默认就落在 Work 里,所以关掉再打开自然找不到。
想长期保存,得先给它一个“硬盘上的家”,也就是自己定义一个逻辑库:
/* 把 D 盘下的 sasdata 文件夹注册成一个逻辑库,别名 mylib */ libname mylib 'D:\sasdata'; /* 引用时写成 逻辑库名.数据集名,文件就真正落到硬盘上了 */ data mylib.sale2024; input month amount; cards; 1 1200 2 1500 3 980 ; run;libname那一句相当于给文件夹起了个短名字,后面所有地方都用这个短名加一个点来引用。mylib.sale2024里的点不是句号,是“逻辑库.数据集”的分隔符,理解成“文件夹里的文件”就对了。
这里有个前提:那个文件夹得先在硬盘上建好,SAS 不会替你新建。文件夹写错、路名拼错,日志里会直接报错,照着改就行。
3. 第一个能跑的例子:三句话建数据集,再做一次分组汇总
上一章跑的那个例子太小了,三条记录,连个头尾都看不出来。这一章我们做一个完整一点的小场景:一批员工的考试成绩,按性别分组算平均分、人数、最高最低分。全程只用编辑器写代码,不点任何菜单。
为什么选这个例子?因为它把 SAS 入门最核心的三件事串起来了:把数据搬进来、对数据分组计算、把结果看懂。这三件事会了,你就已经跨过“什么都不懂”那道坎了。
3.1 逐句拆 data、input、cards:把一张小表搬进 SAS
先看代码,再一句一句拆:
data exam; input id gender $ score; cards; 1001 M 88 1002 F 92 1003 M 75 1004 F 85 1005 F 79 1006 M 91 ; run;第一行data exam;给数据集起名。名字规则不算宽松:只能由英文字母、数字和下划线组成,必须以字母或下划线开头,不能超过 32 个字符,不能有空格、中文和特殊符号。刚入门最保险的做法就是全用英文小写加下划线,比如exam_2024。用中文命名虽然某些设置下能识别,但后面引用、导出、跟别的系统对接时容易出乱子,不建议新手碰。
第二行input id gender $ score;声明变量。id和score后面没跟符号,默认按数值型处理;gender后面跟了一个$,表示这是字符型变量,取值是 M、F 这类文字。这个$忘写是新手的高发错误——SAS 会试图把 M 读成数字,读不进去就变成缺失值,你看到的结果里性别那一列全空,还找不到原因。
第三行cards;之后就是数据本身,一行一条记录,字段之间用空格隔开。SAS 默认以空格作为分隔符,读到空格就认为当前变量结束、开始读下一个。所以数据里如果有空格,比如姓名“张 三”,就会把后面的字段全部挤错位,这种情况要用别的输入方式处理,后面再说。
数据结束的那个分号,必须单独占一行。直接跟最后一条数据后面写,SAS 会把它当成数据的一部分。这是新手排在前几位的翻车点,日志里往往表现为“数据行数不对”或者“某列全是缺失”。
最后一个run;提交执行。跑完去日志看,应该有一行NOTE: 数据集 WORK.EXAM 有 6 个观测和 3 个变量。这句话非常重要,它是你的第一道校验:观测数对不对?变量数对不对?如果这里跟你预期的不一样,后面所有的分析结果都别信。
3.2 用 proc means 算出结果:程序步怎么写、怎么看
数据集有了,接着算:
proc means data=exam mean n min max; class gender; /* 按性别分组 */ var score; /* 只对 score 这一列做统计 */ run;proc means是 SAS 里最常用的描述统计过程。data=exam指明数据来源,后面几个词是要哪些统计量:mean平均值、n有效记录数、min最小值、max最大值。这几个关键字可以自由组合,想要中位数就加median,想要标准差加std。
class gender;是分组语句,意思是“按性别把数据分成几堆,每堆单独算”。如果去掉这一句,得到的就是全体汇总,只有一行。
var score;指定分析对象。如果不写,SAS 会默认把所有数值型变量都算一遍,变量一多结果就乱成一锅粥。所以养成习惯:永远明确写出你要分析哪一列。
结果怎么读?输出里会出现一张表,行是 F 和 M 两组,列是 N、Mean、Minimum、Maximum。你会看到每组的人数、平均分、最低分、最高分。如果某一组的 N 比你在数据里数出来的少,说明那条记录的 score 没读进去,多半是数据那部分写错了,回去数一下行。
这里插一句思路上的事。很多人学 SAS 就停在“记住 proc means 能算平均分”这一层,然后换个场景又不会了。真正有用的是想清楚:我要按什么分组?我要对哪一列算?我要哪几个指标?把这三个问题回答完,代码基本就成型了。书里反复强调的“以解决问题为导向”,说的就是这个意思——先想清楚要什么,再去查语法。
3.3 变量名和分号的规矩:出错多半栽在这两处
刚上手的前两周,你遇到的错误八成集中在两个地方,提前记住能省不少时间。
第一个是分号。SAS 里分号是语句结束的标志,每条语句后面必须跟一个英文状态的分号。中文分号看起来几乎一样,但 SAS 不认,结果是这一句和下一句被强行粘在一起,报错信息还指向莫名其妙的位置。判断方法很简单:报错行号跟你以为的位置对不上,先回去检查分号是不是中文的。
第二个是变量名大小写和引用。SAS 里变量名不区分大小写,Score和score是同一个,但名字拼错就是找不到。写var scores;而数据里叫score,日志会提示变量不存在。这类错误不难改,难的是新手常常不去看日志,直接盯着输出窗口发愁“怎么什么都没有”。
再补一条实用规则:data后面起的名字,跟硬盘上已有文件重名时,SAS 会直接覆盖,不问你。所以起名尽量带上日期或版本,比如exam_0315,能少很多“昨天的结果被今天的覆盖了”的惨案。
4. 数据整理入门:函数、清洗、合并其实是一条链
到这一步,你已经能把数据搬进 SAS 并算出一两个指标了。但真实的数据从来不是干干净净排好队的:有重复录入的、有缺胳膊少腿的、有离谱到不像话的、还有分散在两张表里需要拼起来的。
这一章讲的就是从“能用”到“敢用”的那一段。别被“函数”“清洗”“合并”这几个词吓住,它们其实是一条链上的三个动作:先用函数造出你需要的新列,再用清洗挑出有问题的记录,最后把多张表拼成一张。
4.1 先练三类函数:round、count、日期函数
SAS 的函数有几百个,新手完全不用贪多。先把三类最常用的练熟,覆盖的场景已经超过一半。
第一类是数值处理,代表是round。它的本职是四舍五入,但真正好用的地方在于按区间归组:
data score2; set exam; /* set:把 exam 的数据拿过来 */ grp = round(score, 5); /* 按 5 分一档归组,88 变 90,75 还是 75 */ run;round(值, 基数)的第二个参数是“取整到几的倍数”。写round(score, 5)就得到 75、80、85、90 这样的档位,写round(score, 10)就是 10 分一档。这个用法在分段统计里特别顺手,比写一堆 if 判断简洁得多。
第二类是字符处理,代表是count。它能数出某个词在一段文字里出现了几次:
data feedback; input id comment $30.; cards; 1 质量很好物流也很快 2 一般般吧 3 很好用会回购 ; run; data feedback2; set feedback; n_good = count(comment, '好'); /* 数一数"好"字出现了几次 */ run;count(源字符串, 要找的子串)返回出现次数。做问卷、做评论分析时,用它能快速给每条文字打一个粗略的情绪分。注意中文内容涉及编码设置,实际用之前先确认软件环境的编码,否则可能读出来是乱码——这个坑我踩过,排查了大半天才发现是编码问题,不是函数写错了。
第三类是日期处理,代表是mdy和year、month、day:
data dt; birth = mdy(3, 15, 1995); /* 用 月、日、年 三个数拼成一个日期值 */ y = year(birth); /* 取出年份 */ m = month(birth); /* 取出月份 */ format birth yymmdd10.; /* 让日期显示成 1995-03-15 这种样子 */ run;mdy(月, 日, 年)的参数顺序是月在前、年在后,跟日常书写习惯相反,第一次写基本都会写反。format那句只影响显示,不影响存储的值,所以放心用。日期在 SAS 内部其实是一个数字,从 1960 年 1 月 1 日开始算天数,知道这一点,很多“日期怎么变成数字了”的疑惑就解开了。
4.2 数据清洗三件套:重复值、缺失值、异常值
数据清洗听着高深,落到操作上就是三个动作,每个动作都有现成的写法。
重复值。同一个人被录了两次、同一笔订单出现三条,这类问题最先要处理:
proc sort data=raw nodupkey; /* nodupkey:按 by 变量判重,只保留第一条 */ by id; run;proc sort本来是排序用的,加上nodupkey选项就变成了“排序顺带删重”。by id;说明按 id 判断是不是同一个人。它保留的是排序后的第一条,如果你需要保留最新的一条,就得先按时间倒序排,再删重。
缺失值。找缺失值最直接的办法是用missing()函数:
data miss; set raw; if missing(score) then flag = 1; /* 数值型和字符型都能判断 */ else flag = 0; run;missing()的好处是数值和字符通用,不用记两套写法。数据里数值缺失显示为一个点.,字符缺失显示为空白,肉眼很难扫出来,尤其是几万行的时候,所以交给程序判断。
变量一多,一列一列写就不现实了。这时候用数组,能写出一段通用的程序:
data _null_; /* _null_:只跑逻辑,不生成数据集 */ set raw; array num[*] _numeric_; /* 把所有数值变量装进数组 num */ array ch[*] _character_; /* 把所有字符变量装进数组 ch */ do i = 1 to dim(num); if missing(num[i]) then put "第 " _n_ " 行 " vname(num[i]) " 缺失"; end; do i = 1 to dim(ch); if missing(ch[i]) then put "第 " _n_ " 行 " vname(ch[i]) " 缺失"; end; run;_numeric_和_character_是 SAS 的自动变量列表,代表“所有数值变量”和“所有字符变量”,不用你一个个点名。dim()返回数组长度,vname()返回变量名,_n_是当前处理到第几行,put把结果打到日志。这段程序不管你表里有 5 列还是 500 列,都能直接跑,属于值得抄下来存着的那种。
异常值。先看清楚分布,再定规则。用proc means加上极值就能有个大概:
proc means data=raw n min max mean std; var amount; run;看最小值是不是负数、最大值是不是离 Mean 差了好几个标准差。真实业务里的异常值没有统一标准,别人的规则搬过来不一定适用。稳妥的做法是先看分布,再跟业务方确认“多大算离谱”,然后写条件筛出来人工核对,别直接删。
4.3 set 纵向合并和 merge 横向合并,别用反
数据分散在两张表里是常态:一张有基本信息,一张有交易记录,得拼起来才能分析。
纵向合并用set,就是上下摞起来:
data all; set jan feb mar; /* 把三个月份的数据集上下摞成一个 */ run;前提是列名对得上。列名一样的对齐,只在一张表里出现的列,其他表对应位置就是缺失。这种合并适合“同一种结构、不同时间段”的数据。
横向合并用merge,就是左右拼起来:
proc sort data=a; by id; run; /* 合并前必须先按 id 排序 */ proc sort data=b; by id; run; data ab; merge a b; by id; /* 按 id 一一对应拼起来 */ run;merge有一条硬规矩:参与合并的数据集必须先按 by 变量排好序。没排序就直接 merge,日志里会冒出警告,结果可能是错的,而且错得不明显——这是最坑的一种情况,因为程序不报错,你还以为跑成功了。我见过有人拿这个结果做了两周的报表才发现对不上,返工时的那种心情,经历过一次就再也不会忘了。
5. 常见问题排查:新手最容易被卡住的五个地方
新手卡住的时候,往往不是不会写,而是不知道错在哪。这一章把最常见的五种情况列出来,按“现象 → 原因 → 解决”说清楚,遇到问题时对着找就行。
5.1 日志里一片红,光标指向奇怪的位置
现象:程序一提交,日志里出现 ERROR,提示的行号跟你以为的出错位置对不上,有时候整段代码都被标红。
原因:九成是分号的问题。要么是漏写了,要么是写成了中文分号。SAS 靠分号判断语句边界,一个分号不对,后面几句会被连成一句,报错位置自然就跑偏了。
解决:从报错位置往上找最近的一个分号,检查是不是英文状态。还有个笨办法但很有效:把这段程序单独复制到一个空文件里,一行一行提交,哪一行开始出错就一目了然。
5.2 数据读进来了,可某一列全是空的
现象:日志显示数据集建好了,观测数也对,但打开一看,某个本该有值的列全是缺失。
原因:变量类型和数据的实际形态不匹配。最常见的是字符型变量忘了加$,SAS 拿数字规则去读字母,读不进去就置空。另一种是数据行里的字段数比input声明的少,后面几列就自动变成缺失。
解决:先核对input语句里的变量个数和类型,字符型一定要带$。再把数据区前几行拿出来,数一下每行有几个字段,跟变量数对上。数据里带空格的字段,比如姓名中间有空格,会被当成两个字段,这种要另外处理。
5.3 合并之后记录数不对,多出来或者少了一大截
现象:两张表分别有 1000 行和 500 行,merge 之后变成 1200 行或者 800 行,跟预期的对不上。
原因:三种可能。一是合并前没排序,SAS 按当前顺序硬拼,结果随机;二是 by 变量在两边的类型不一致,一边是字符一边是数值,匹配不上;三是两张表里 by 变量有重复值,一对多会让行数翻倍。
解决:merge 之前先对两张表各跑一次proc sort,排序完顺便看一眼有没有重复的 id。确认 by 变量类型一致。合并后立刻用proc means或日志里的观测数对比一下,行数异常就停下来查,别带着错数据往下做。
5.4 关掉软件再打开,昨天建的数据集不见了
现象:明明昨天建好了数据集,今天打开 SAS,资源管理器里 Work 下面空空如也。
原因:数据集建在了 Work 这个临时逻辑库里。SAS 一关闭,Work 自动清空,这是设计如此,不是软件坏了。
解决:先libname定义一个指向硬盘文件夹的逻辑库,再用逻辑库名.数据集名的方式建数据集。养成习惯:练习用的数据放 Work 无所谓,要留着的数据一律放自己定义的逻辑库。
5.5 画图、制表的程序跑不动,或者图出来是空白
现象:写好的proc sgplot或proc tabulate提交后没反应,或者出来一张空图、一个空表。
原因:常见的有三种。一是data=指向的数据集不存在,或者名字拼错;二是语句里指定的变量名跟数据集里的对不上;三是导出到外部文件时,路径里的文件夹不存在,或者路径中用了中文和空格。
解决:先看日志里有没有“数据集不存在”或“变量未找到”的提示,逐字核对名字。导出文件时,路径先用全英文、无空格的目录试一次,通了再改。图出来是空白的话,检查var或x=y=指定的变量是不是全为缺失值——数据本身是空的,图画出来当然也是空的。
6. 下一步学什么:先画图还是先制表,给你的顺序表
走到这里,你已经能建数据集、算指标、洗数据、合并表了。接下来往哪走,很多人会卡一下:书里后面讲了绘图、讲了制表、讲了输出到 Word 和 Excel,内容不少,一起上容易晕。
我给的建议是:先制表,再画图,最后碰模板。理由很实在——制表是每天都要交的东西,图是偶尔要交的东西,模板是几乎不用自己写的东西。先学高频的,收益最快。
顺着这个顺序,可以这么排:
| 阶段 | 学什么 | 大概花多久 | 判断学会的标准 |
|---|---|---|---|
| 第一阶段 | proc tabulate做常规汇总表、三线表 | 一到两周 | 能独立做出一张能直接交上去的月度汇总表 |
| 第二阶段 | proc sgplot画柱状图、散点图、折线图 | 两到三周 | 能根据数据特点选对图型,并调好坐标轴和标签 |
| 第三阶段 | 用 ODS 把结果输出到 Word、Excel、PDF | 一周 | 一条程序跑完,文件直接生成在指定目录 |
| 第四阶段 | 双坐标轴、瀑布图、热图这类进阶图形 | 按需 | 遇到具体需求时能查着文档做出来 |
第一阶段先啃proc tabulate。它的价值在于把“分组 + 统计量 + 排版”一次性搞定,做出来的三线表可以直接进报告。新手常犯的错是一上来就去研究怎么调表格边框、怎么改字体大小,其实先把行列结构搭对,样式的事放到最后调,效率高得多。
第二阶段学proc sgplot。它比老式绘图过程好用,语法也更接近自然语言:说明 X 轴是什么、Y 轴是什么、用什么图形,三句话就能出一张图。学的时候别贪多,先把柱状图、散点图、折线图这三种练到不用查文档,覆盖的场景已经够用了。图形好不好看,很大程度上不在代码,而在你有没有想清楚“这张图要让人一眼看出什么”。
第三阶段是 ODS。这东西的价值在自动化:每个月数据一更新,跑一遍程序,Word 报表自动生成在指定文件夹里,不用再手工复制粘贴。第一次配通的时候会有点折腾,配通之后每个月省下的时间非常可观。
至于模板、地图、雷达图这些,等你把上面三阶段走顺了再回头看,会发现它们只是同一套思路的延伸:数据进来、加工、输出。差别只在输出那一步用了哪个过程。
最后说个我自己的习惯。刚学的时候我总想一口气把整本书读完,结果读到绘图那一章就卡住了,前面的数据步反而忘得差不多。后来我改成:每学一个过程,就拿自己手上真实的数据跑一遍,跑通了再往下。学 SAS 这件事,看十遍不如自己写一遍跑通一遍。从那以后我每次学新东西,都强制自己先用最小的一份数据跑通,再去看进阶用法。希望这个习惯也能帮到你。
本文还有配套的精品资源,点击获取