1、第第5章章 数据步读入原始数据数据步读入原始数据清华大学经管学院清华大学经管学院 朱世武朱世武ZResdat样本数据:样本数据:SAS论坛:论坛: 原始数据分类原始数据分类 原始数据一般分为字符和数值两种类型,数值数据又分为标准数值数据和非标准数值数据。标准数据标准数据是由字符或者数值组成的可以被列表、列、格式化、命名输入方式读入的数据如ARKANSAS,1166.42。非标准数据非标准数据只能在输入格式的帮助下读入的数据。如非标准的数值数据,可能包含逗号,空格等符号。日期和时间数值。十六进制和二进制数值。标准数值数据标准数值数据只包含数字,小数点或负号。非标准数值数据非标准数值数据则包含其它
2、的特殊字符,如千分号,美元符号等。 读取数值数据的规则数值前面的括号或者减号符号表示该数值为负。首位有一个或者多个零不影响对相应变量的赋值。SAS不把数值尾部的空格默认为0。数值数据的前后都可以有空格,但是数字中间不能有(除非用COMMA. 或BZ.格式读入)。字符数据字符数据 字符数据是由一系列字符组成的数据。下面任一种情况下,INPUT语句认定读入变量的值是字符值。INPUT语句中变量名后跟一个美元符号$;使用字符输入格式;要读入数据的变量已经被定义为字符值。原始数据呈现形式原始数据呈现形式 原始数据的呈现形式一般分为呈现在SAS编辑窗口的数据行,和储存在外部文件中的原始数据例例5.1 编
3、辑窗口下,数据行形式的原始数据。data weight; input PatientID $ Week1 Week8 Week16; loss=Week1-Week16; datalines;2477 195 177 1632431 220 213 1982456 173 166 1552412 135 125 116;例例5.2 储存在外部文件中的原始数据,TXT文本格式。-1-22477 195 177 1632431 220 213 1982456 173 166 1552412 135 125 116使用使用INPUT语句读入原始数据语句读入原始数据 INPUT语句的用途有两方面:读入
4、外部数据文件中的数据;读入CARDS语句后面的数据。 INPUT语句的五种输入方式语句的五种输入方式 简单方式:INPUT ; 列方式:INPUT variable start-column ; 格式化方式:INPUT variable informat. ; INPUT (variable-list) (informat-list) ; INPUT (variable-list) ( informat.); 列表方式:INPUT variable ; INPUT variable ; 命名方式:INPUT variable= ; INPUT variable= start-column ;
5、INPUT variable=informat. ; 选项说明specification(s)变量及其格式的详细说明variable-list列出要读入数据值的变量执行下一个INPUT语句时指针移到下一记录行,要求一条记录必须对应一个数据行执行下一个INPUT语句时指针保持在当前记录行,不要求一条记录对应一个数据行$ 定义字符型变量start-column规定变量值在记录行中的起始列end-column规定变量值在记录行中的终止列decimalplaces小数点位置pointer-control 移动输入指针到指定的行或列上informat 列出变量的输入格式;informat-list -列
6、出变量列表对应的输入格式列表decimals规定小数部分的位数列方式输入列方式输入 语句格式INPUT variable start-column ; 设定变量名称,为可选项,如果选择$则表示这是一个字符变量。而start-column 表示该变量在记录行中的起始列(终止列)。例例5.3 使用列方式输入数据。data scores;infile datalines truncover;input name $ 1-10 sex $11 age 12-15 ;datalines;Justine F 12Bob M 13;-+-1-+-2-+-3-+- 例中,规定记录行的第1到10列为变量NAME
7、的输入值,11列为变量SEX的输入值,12到15列为变量AGE的输入值。NAME和SEX为字符型变量。列方式输入使用条件列方式输入使用条件原始数据输入值的位置在每个记录行相同的列中; 原始数据输入值是标准的数值格式或一般字符格式。列方式输入的特点列方式输入的特点原始数据输入值可以按任意顺序读取;字符型原始数据中间可以有空格;可以重复读取原始数据记录行的某一部分。读入的数据值不需要用空格或者其它分隔符隔开。列表方式输入列表方式输入 简单列表方式输入简单列表方式输入INPUT variable ; 调整列表方式输入调整列表方式输入INPUT variable ;列表方式输入使用条件输入数据值之间至
8、少有一个至少有一个空格隔开;用小数点表示表示缺失值;字符型值的默认长度为8个字节,也可以用LENGTH, ATTRIB, INFORMAT语句规定长度;数据必须是字符数据或标准的数值数据。数据必须是字符数据或标准的数值数据。列表方式输入格式修饰符 :当原始数据是以空格为分隔符时,要想对变量值长度不一致的变量规定统一长度就必须用到该格式修饰符。规定变量值是从非空格列中读取, 直到第一次遇到以下三种情况之一,该变量值的读取过程才结束:l 下一个空格列;l 达到变量预先设定的长度(如果没有预先设定变量长度就是SAS默认字符长度8个字节);l 数据行结束。例例5.5 空格为分隔符时,对变量值长度不一致
9、的变量规定统一长度。data;input Univ : $12. Plc$ Zip ;cards;MIT Boston 100023 TsinghuaUniv Beijing 100084;例中,第一个观测变量Univ的值为MIT(只读3个字符,因遇到空格而结束)第二个观测值为TsinghuaUniv(得到先前定义的变量长度12)。如果只对变量Univ规定长度,而不加格式修饰符(:),在读入第一条记录时就会出错,如果不对变量Univ规定长度,读入第二条记录时就会只读入Tsinghua,而不是预先要读入的TsinghuaUniv,这是因为SAS默认的字符变量的存储长度就是8个字节。UnivPlc
10、ZipMITBoston100023TsinghuaUnivBeijing100084加格式修饰符(:)不加格式修饰符(:)UnivPlc ZipMIT Boston 100023 .&字符型输入值可能包含一个或几个空格。因为空格是列表读入方式默认的分隔符,所以,如果要读入的数据值本身包括空格时就必须用此格式符。例5.6 空格为分隔符时,字符型输入值嵌有空格。data ;input name & $12. age;cards;Jiang Zhu 20Annie Zheng 31I. Altman 60;run;例中,第一个观测name 中Jiang Zhu (包含一个空格),第二个观测为Ann
11、ie Zheng (包含一个空格)。分隔符为两个空格。注意:因注意:因&有以上特性,数据之间应该用两个以上的空格隔开。有以上特性,数据之间应该用两个以上的空格隔开。规定读入字符值时保留引号。此选项只在INFILE语句中与选项DSD一起使用时才有效。注意:DSD选项在第六章会有详细介绍。这里先说明它的4个功能:l 将默认分隔符改为逗号;l 对于连续的两个分隔符,中间按缺失值处理;l 将字符变量值的引号去掉;l 对引号里的分隔符按字符来对待。所以INFILE语句中的DSD选项自动把数据记录的分隔符设置为逗号,并且读入数据之前,把字符数据中的引号去掉,若加上就会保留数据中的引号。可以通过下面的这个例
12、子来理解DSD和的作用。例例5.7 DSD和的作用,读入字符值时保留引号。 只在INFILE语句中与选项DSD一起使用时才有效。data topics2;infile datalines dsd;input speakers : $15. title $40. location & $10.;datalines;Song, Credit Derivatives, Room 329Zhu, Credit Risk Management, Room 406;proc print;run;由上例可以看出,“”包含包含“:”选项的功能选项的功能。例中,虽然title变量的长度是40,而观测值得长度都不
13、到40,仍然可以得到正确结果。所以“”包含 “:”的功能。 把speakers后面的“:”改成了“”也可以。例如:data topics2;infile datalines dsd;input speakers $15. title $40. location & $10.;datalines;Song, Credit Derivatives, Room 329Zhu, Credit Risk Management, Room 406;proc print;run;输出窗口信息:Obs speakers title location 1 Song Credit Derivatives Room
14、 329 2 Zhu Credit Risk Management Room 406 但是,若把title后成的“”改成 “:”,引号就因为dsd选项的存在被去掉。如下:data topics2;infile datalines dsd;input speakers : $15. title :$40. location & $10.;datalines;Song, Credit Derivatives, Room 329Zhu, Credit Risk Management, Room 406;proc print;run;输出窗口信息Obs speakers title location
15、1 Song Credit Derivatives Room 329 2 Zhu Credit Risk Management Room 406格式化方式输入格式化方式输入 格式化输入方式是INPUT语句读取非标准数据读取非标准数据的唯一方法。即在变量名后面规定输入格式。这种输入方式不仅给出了该输入数据所对应的类型,而且给出了输入数据所在列的长度。语句格式:语句格式:INPUT variable informat. ; INPUT (variable-list) (informat-list) ; INPUT (variable-list) ( informat.); 其中:n*规定在输入列表
16、中后面的输入格式重复n次。例例5.8 格式化方式输入。data;infile datalines;Input (X1-X5) (3*7.2, 2*5.2);.例中,前3个变量X1-X3的格式为7.2,而后2个变量X4-X5的格式为5.2例例5.9 读入非标准数据$1,000.22。data one;input x comma9.2;datalines;$1,000.22;run;例中,读入的数据为1000.22,这里要注意长度,该数据符号加上数字一共是九列。命名方式输入命名方式输入 如果数据行中含有变量的名字,后面跟着等号和变量的值,读取数据时应该使用命名输入方式。语句格式INPUT vari
17、able= ; INPUT variable= start-column ; INPUT variable=informat. ; 其中:variable=规定用于INPUT语句读入的变量名。例例5.11 使用命名输入格式。data a;input date yymmdd10. fullshr stkcd=$ lstknm=$ ;cards;2001-01-18 1486553100 stkcd=600001 lstknm=邯郸钢铁;run;后面变量的不采用命名输入格式,读入数据时出错。data a;input date yymmdd10. stkcd=$ lstknm=$ fullshr;c
18、ards;2001-01-18 stkcd=600001 lstknm=邯郸钢铁 1486553100;run;Log窗口显示出错信息:NOTE: LOST CARD.RULE: -+-1-+-2-+-3-+-4-+-5-+-6-+-7-+-8-date=14993 stkcd=600001 lstknm=邯郸钢铁 fullshr=. _ERROR_=1 _N_=1NOTE: INPUT 语句到达一行的末尾,SAS 已转到新的一行。NOTE: 数据集 WORK.A 有 0 个观测和 4 个变量。第第20章章 SQL从单个表中检索数据从单个表中检索数据清华大学经管学院清华大学经管学院 朱世武朱世
19、武ZResdat样本数据:样本数据:SAS论坛:论坛: SELECT语句综述语句综述 SELECT语句是PROC SQL的主要工具。使用SELECT语句可以识别、检索和操作表中的数据,使用SELECT子句可以设定查询条件。SELECT语句格式语句格式 SELECT object-item INTO macro-variable-specification FROM from-list GROUP BY group-by-item ORDER BY order-by-item ; SELECT 子句子句 语句格式语句格式SELECT object-item FROM from-list选择所有列
20、选择所有列 语句格式:COLUMN-NAME= * (asterisk) select * from from-listSELECT子句中,“*”号表示选择表中的所有列。例:例:proc sql outobs=3; select * from ResDat.dret;选择特定列选择特定列 语句格式:Select column-name from from-list例例20.120.1 选择特定列。proc sql outobs=3;title 股票代码;select stkcd from resdat.lstkinfo;proc sql outobs=3;title 股票代码和名称;selec
21、t stkcd,lstknm from resdat.lstkinfo;quit;用用DISTINCT语句剔除查询结果中重复观测语句剔除查询结果中重复观测 语句格式:=distinct例例20.2 删除重复观测。proc sql; select distinct stkcd from ResDat.yrret;quit;创建说明列创建说明列 语句格式:SELECT TEXT, COLUMN-NAME例20.4 创建说明列。proc sql outobs=3; select Stock Code for, lstknm, is, stkcd from ResDat.lstkinfo; quit;
22、 输出窗口结果: 最新股票名称| Latest Stock 股票代码|Sto Name ck Code - Stock Code for S深发展A is 000001 Stock Code for 万科A is 000002 Stock Code for *ST国农 is 000004计算新列值计算新列值 语句格式:Calculating Values =Calculating Expression of columns 例例20.5 计算股票每日成交金额。proc sql outobs=3; title Trading Sum; select stkcd, lstknm, clpr*trd
23、vol format=12.2 from ResDat.qttndist;quit; Trading Sum 最新股票名称| 股票代码|Sto Latest Stock ck Code Name - 000001 S深发展A 3946648.52 000001 S深发展A 1420743.60 000001 S深发展A 1120732.50为列分配别名为列分配别名 语句格式:SELECT calculation-form 别名必须符合SAS名称要求,别名只在当前的查询中有效。例例20.6 为列分配别名。proc sql outobs=3; title Trading Sum; select s
24、tkcd, lstknm, clpr*trdvol as trdsum format=12.2 from ResDat.qttndist;quit; Trading Sum 最新股票名称| 股票代码|Sto Latest Stock ck Code Name trdsum - 000001 S深发展A 3946648.52 000001 S深发展A 1420743.60 000001 S深发展A 1120732.50CALCULATED 语句语句 语句格式:Calculated Column-name使用别名引用一个计算过的列值时,必须使用Calculated 关键词,并将Calculated
25、放在列名称之前,以此告知PROC SQL这个列是经计算得到的。proc sql outobs=3;select stkcd,lstknm,date,clpr*mcfacpr as adjpr format 8.2,(calculated adjpr*trdvol) as trdsum format 12.2 from resdat.qttndist;quit; 最新股票名称|股票代码|Sto Latest Stockck Code Name 日期|Date adjpr trdsum -000001 S深发展A 1991-01-02 66.94 3946648.52000001 S深发展A 19
26、91-01-03 66.89 1420743.60000001 S深发展A 1991-01-04 66.75 1120732.50CASE表达式表达式 语句格式: CASE WHEN when-condition THEN result-expression END例例20.7 简单形式的Case表达式。proc sql outobs=3;select stkcd,lstknm,lstdt, case when exchflg=1 then 上交所 when exchflg=2 then 深交所 else 所有交易所 end as exchflgfrom resdat.lstkinfoorde
27、r by lstdt; quit;例中,将股票信息表lstkinfo交易所标识(exchflg)的编码值进行转换,同时得到新的交易所标识列及相关数值。 最新股票名称|股票代码|Sto Latest Stock 股票上市日|Lck Code Name ist Date exchflg-000005 ST星源 1990-12-10 深交所600652 爱使股份 1990-12-19 上交所 600602 广电电子 1990-12-19 上交所使用使用ORDER BY语句排序语句排序 语句格式语句格式ORDER BY order-by-item , . order-by-item ; 选项说明: o
28、rder-by-item 可以是如下: integer等同于一个列在SELECT子句中的位置column-name列的名称或者别名sql-expression见附录中的sql-expressionASC升序排列数据,默认方式DESC降序排列数据例例20.9 对股票上市时间列进行排序。proc sql outobs=3;select lstknm,lstdt from resdat.lstkinfoorder by lstdt; quit;最新股票名称|Latest Stock 股票上市日|LName ist Date-ST星源 1990-12-10爱使股份 1990-12-19广电电子 199
29、0-12-19可以通过指定列在SELECT子句中的整数位置对该列排列。例例20.11 按第4列排序。proc sql outobs=3;select stkcd,lstknm,date,clpr*mcfacpr as adjpr format 8.2from resdat.qttndistorder by 4 desc;quit; 最新股票名称|股票代码|Sto Latest Stockck Code Name 日期|Date adjpr-600652 爱使股份 2001-05-15 105881.8600652 爱使股份 2001-05-16 103950.1600652 爱使股份 2001
30、-05-14 103020.1用用WHERE语句选择观测语句选择观测 语句格式语句格式WHERE sql-expression 选项说明: sql-expression (见sql-expression定义). 例例20.13 用WHERE语句选择1991年以前上市的股票。proc sql outobs=3;select lstknm, lstdt from resdat.lstkinfo where lstdt31dec1991d;quit; 最新股票名称|Latest Stock Name 股票上市日|List Date-S深发展A 1991-04-03万科A 1991-01-29*ST国
31、农 1991-01-14使用使用IN算符算符例20.14 简单IN算符用法。proc sql outobs=3;select lstknm, stkcd from resdat.lstkinfo where stkcd in (000001 600651 000004);quit;最新股票名称| Latest Stock Name 股票代码|Stock Code-S深发展A 000001*ST国农 000004飞乐音响 600651使用使用BETWEEN-AND 算符算符 例例20.16 使用BETWEEN-AND算符选择满足一定范围的观测。proc sql;create table stki
32、nfo1991 as select * from resdat.lstkinfowhere lstdt between 1jan1991d and 31dec1991d;quit;使用使用LIKE算符算符 例例20.17 使用匹配算符LIKE选择观测。proc sql;select stkcd,lstknm from resdat.lstkinfo where lstknm like ST%;quit;股票代码|Sto ck Code 最新股票名称| Latest Stock Name -000005 ST星源600603 ST兴业使用汇总函数汇总数据使用汇总函数汇总数据 使用汇总函数(agg
33、regate function or summary function)可以产生数据的统计量。 用用WHERE子句汇总数据子句汇总数据 例例20.19 使用乘法函数算出代码为000002的股票调整后的收盘价。proc sql outobs=3;select stkcd,lstknm,clpr*mcfacpr as adjpr from resdat.qttndist where stkcd=000002;quit; 最新股票名称| 股票代码|Sto ck Code Latest Stock Name adjpr -000002 万科A 15.52000002 万科A 15.57 000002
34、万科A 15.48使用使用SUM函数函数 例例20.20 使用sum函数计算深发展历年派发现金红利总额。proc sql;select sum(dividend) format=8.2 as totledv from resdat.stk000001;quit; totledv- 2.70观测数汇总观测数汇总 语句格式:Select count(distinct ) as proc sql;title Number of total Rows;select count(*) as number from resdat.lstkinfo;quit;Number of total RowsNumb
35、er- 30使用使用GROUP BY子句进行分组汇总子句进行分组汇总 语句格式语句格式GROUP BY group-by-item 选项说明: integer等同于一个列在SELECT子句中的位置Column-name列的名称或别名Sql-expression见附录sql-expression例例20.22 分组进行汇总。proc sql outobs=3;title 2005年股票月收益平均值;select stkcd, avg(monret) from resdat.monret where 1jan2005d=date=31dec2005d group by stkcd;quit;200
36、5年股票月收益平均值 股票代码|Stock Code-000001 -0.0017000002 0.025023000004 -0.03469用用HAVING子句选择分组数据子句选择分组数据 语句格式语句格式例例20.25 算出A股市场股票2005年的交易天数。proc sql;select stkcd,count(*)as trday from resdat.dretwhere 1jan2005d=date=31dec2005dgroup by stkcdhaving substr(stkcd,1,1) in (0,6) or substr(stkcd,1,2)=99;quit;股票代码|Stock Code trday-000002 212000007 241000011 230000016 239600601 241600604 232600651 239600653 240