《深入解析sas:数据处理、分析优化与商业应用》一3.3 创建新变量

本节书摘来自华章出版社《深入解析sas:数据处理、分析优化与商业应用》一书中的第3章,第3.3节,作者 夏坤庄 徐唯 潘红莲 林建伟,更多章节内容可以访问云栖社区“华章计算机”公众号查看

3.3 创建新变量

在对SAS数据集进行处理时,经常需要根据原有变量或变量值生成新变量。根据要实现功能的不同,SAS提供了多种方法,例如通过数据集选项RENAME=(RENAME语句)、赋值语句、求和语句等来实现不同的功能。

3.3.1 数据集选项RENAME=和RENAME语句

在DATA步中,可使用数据集选项RENAME=或RENAME语句修改一个或多个变量的名称。跟前面介绍过的数据集选项KEEP=和DROP=一样,数据集选项RENAME=也可用于DATA语句中的输出数据集和SET语句中输入数据集。其基本形式如下:

RENAME=(旧变量名-1=新变量名-1 <...旧变量名-n=新变量名-n >)
RENAME语句的基本形式如下:
RENAME 旧变量名-1=新变量名-1 <...旧变量名-n=新变量名-n >;

其中:
旧变量名指定在输入数据集中或当前DATA步中新创建的变量。
新变量名指定在输出数据集中使用的变量名或变量名称列表。新的变量名仅被写入输出数据集。
数据集选项RENAME=或RENAME语句可以修改多个变量的名称。
例3.17:将数据集saslib.contact2中的变量Name重命名为Full_Name,并将原有Name中的姓和名分开为Last_Name和First_Name。
下面3段代码分别在SET语句中使用数据集选项RENAME=、在DATA语句中使用数据集选项RENAME=和使用RENAME语句来实现。
代码1:

data work.contact2_rn;
    set saslib.contact2 (rename=(Name=Full_Name));
    First_Name=scan(Full_Name,1);
    Last_Name=scan(Full_Name,2);
run;

代码2:

data work.contact2_rn (rename=(Name=Full_Name));
    set saslib.contact2;
        First_Name=scan(Name,1);
    Last_Name=scan(Name,2);
run;

代码3:

data work.contact2_rn ;
    set saslib.contact2;
    rename Name=Full_Name;
    First_Name=scan(Name,1);
    Last_Name=scan(Name,2);
run;

这3段代码中都使用了SCAN函数,将原Name变量中用空格隔开的姓和名提取到变量Last_Name和First_Name中。注意,在引用原Name变量进行操作时,代码1使用了新变量名(Full_Name)、代码2和代码3使用了旧变量名(Name)。这是因为在SET语句中使用选项RENAME=时,SAS为输入数据集所创建的PDV中的变量名就成为了新变量名,所以在编程语句中引用原变量时必须使用新的变量名。但是如果在DATA语句中使用选项RENAME=或RENAME语句,新变量名仅会写入输出数据集,所以在DATA步的其他语句中引用该变量时,必须使用旧的变量名。
PRINT过程打印3段代码的输出数据集work.contact2_rn的内容相同,如图3.20所示。

《深入解析sas:数据处理、分析优化与商业应用》一3.3 创建新变量

在SET语句中使用数据集选项RENAME=、在DATA语句中使用数据集选项RENAME=和使用RENAME语句的比较如下:
RENAME语句不能用于PROC步,但是数据集选项RENAME=可以。
数据集选项RENAME=可以对每个输出数据集的变量单独更改名称,而RENAME语句修改的变量名称对所有输出数据集都起作用。
SET语句中的数据集选项RENAME=会修改变量名,此时,在编程语句中引用原变量时必须使用新的变量名;如果在输出数据集中使用RENAME=选项或使用RENAME语句,在编程语句引用原变量时必须使用旧的变量名。

3.3.2 赋值语句创建新变量

在DATA步中出现的变量,如果不属于输入数据集的变量,而且也不是自动变量,SAS则会为其创建新变量,所创建的新变量默认会写入输出数据集。可以通过前面介绍的数据集选项DROP=、KEEP=、DROP语句、KEEP语句保留或删除不需要的中间变量。
赋值语句是常见的创建新变量的方法,通常将新变量放在赋值语句的等号(=)左侧来创建新变量,并同时给该变量赋值。在前面的例子已经看到了使用赋值语句修改已经存在的变量值(例3.8~例3.12)和创建新变量(例3.17)。
例3.18:数据集saslib.revenue_quarter中存储了公司产品今年不同季度的销售额,年底要计算全年的总销售额。
该数据集在VIEWTABLE窗口中打开如图3.21所示。

《深入解析sas:数据处理、分析优化与商业应用》一3.3 创建新变量

下面对各季度的销售额(Rev_Q1、Rev_Q2、Rev_Q3和Rev_Q4)相加得到总销售额Total_Rev,最后使用FORMAT语句修改其输出格式。

data work.revenue;
    set saslib.revenue_quarter;
    Total_Rev = Rev_Q1 + Rev_Q2 + Rev_Q3 + Rev_Q4;
    format Total_Rev DOLLAR10.;
run;

所生成的数据集work.revenue在VIEWTABLE窗口中打开如图3.22所示。该数据集包含了表示全年总销售额的变量Total_Revenue。

《深入解析sas:数据处理、分析优化与商业应用》一3.3 创建新变量

3.3.3 对多个观测求和

对数据集进行处理时,经常会需要获得整个数据集中的所有观测或特定一部分观测中的变量值的总和,例如,公司所有产品的总销售额、产品在各地区的总销售额等。在DATA步中,可使用求和语句、RETAIN语句、SUM函数等方式对多个观测中的变量值进行求和。
1.?求数据集中变量的总和
求和语句的基本形式如下:

变量+表达式;

其中:
变量指定累加变量的名称,该变量包含一个数字值。
表达式是任意的SAS表达式。当迭代中表达式的值为缺失值时,SAS会将表达式的求值结果当作0处理。
SAS在读取第一个观测前将求和语句中的累加变量的初始值设置为0。如果要将求和变量的初始值设置为其他的值,可使用RETAIN语句(后面介绍)。
在每次迭代中,SAS执行该语句时将表达式的值与该变量的值相加,结果保持在该累加变量中,下次迭代时仍然可以使用。在一次迭代中,当表达式不为缺失值时,求和语句等同于赋值语句“变量=变量+表达式;”。在求和语句中,当表达式为缺失值时,SAS将表达式的值当作0处理,而赋值语句不会这样。
例3.19:读入公司销售数据建立数据集,并计算总销售额。
公司所有员工销售数据所在外部数据文件sales.dat的内容如下:

ET001,Kevin Lee,TSG,$10000
ED002,Faith May,CSG,$12000
ET004,Jackson Cook,TSG,$18000
EC002,Hailey Leonard,CSG,$23000
ED004,Jack Smith,QSG,$5000

为了让所生成的数据集中的变量Sales和Total_Sales的输出格式同输入格式一样,在DATA步使用FORMAT语句指定变量Sales和Toal_Sales的格式为DOLLAR10.。关于FORMAT语句本书第5章会介绍。

filename exfiles "c:\sas\data";
data saslib.sales;
    length Name $20;
    infile exfiles(sales) dsd;
    input Emp_ID $ Name $ Dept $ Sales:COMMA10.;
    format Sales DOLLAR10.;
run;

data work.sales_sum;
    set saslib.sales;
    Total_Sales+Sales;
    format Total_Sales DOLLAR10.;
run;

proc print data=work.sales_sum noobs;
run;

PRINT语句打印所生成的数据集数据如图3.23所示。其中,变量Toal_Sales为前面所有观测中变量Sales值之和。
例3.20:计算公司所有销售人员的总销售额。与上例不同的是,销售数据中存在缺失值。
包含缺失值的数据集的内容如图3.24所示。
使用求和语句对Sales变量进行求和的代码如下:

data work.sales_sum;
    set saslib.sales2;
    Total_Sales+Sales;
    format Total_Sales DOLLAR10.;
run;

对Sales求和后得到的数据集如图3.25所示。因为第三条观测中的Sales为缺失值,求和语句将其当作0处理,所以第三条观测的Total_Sales值与第二条相同。
     
《深入解析sas:数据处理、分析优化与商业应用》一3.3 创建新变量

2.?求每个BY组的总和
前面提到过,SAS会为BY语句中指定的每个变量生成临时变量FIRST.变量和LAST.变量。在分组数据中,可以使用这两组临时变量计算每个分组中变量值的总和。
例3.21:数据集sashelp.shoes中的观测已经按照地区(Region)、附属品牌(Subsidiary)进行了排序。现在分别计算各地区各附属品牌的销售额总和。
代码如下:

data work.shoes_subsidiary (drop=Sales);
    set sashelp.shoes (keep=Region Subsidiary Sales);
    by Region Subsidiary;

    if First.Subsidiary then
        Total_Sales_Subsidiary=0;

    Total_Sales_Subsidiary+Sales;

    if Last.Subsidiary;

    format Total_Sales_Subsidiary DOLLAR10.;
run;

代码说明如下:
在SET语句中,数据集选项KEEP=指定仅读取输入数据集中的变量Region、Subsidiary和Sales。
在BY语句中,指定BY变量Region和Subsidiary。要求SET语句中的数据集已经按照Region和Subsidiary排序。SAS自动生成临时变量First.Region、Last.Region、First.Subsidiary 和Last.Subsidiary。其中First.Region、Last.Region在本例中未用到。
因为需要计算各附属品牌的总销售额,所以每次出现新品牌(First.Subsidiary为1)时将累加变量,并将Total_Sales_Subsidiary置为0。
求和语句将对Sales值进行累加,结果存储在Total_Sales_Subsidiary中。
当Subsidary的值为该分组内最后一个值(Last.Subsidiary为1)时,才将当前输出PDV中的观测输出,此时Total_Sales_Subsidiary为该品牌的总销售额。当前输出PDV中的变量为Region、Subsidiary、Sales和Total_Sales_Subsidiary。
由于输出观测中的变量Sales为每个分组内最后一个产品的销售额,没有意义,因此在DATA语句中使用数据集选项DROP=指明不将变量Sales写入输出数据集work.shoes_subsidiary。
此外,FORMAT语句在编译时指定累加变量Total_Sales_Subsidiary的输出格式为DOLLAR10.。
所生成的work.shoes_subsidiary在VIEWTABLE窗口中打开如图3.26所示。
《深入解析sas:数据处理、分析优化与商业应用》一3.3 创建新变量

3.?使用RETAIN语句保持变量值
默认情况下,DATA步中所有变量在每次迭代开始前都会被设置为缺失值。而RETAIN语句中指定的变量则不会,其值会一直保持着,在下次迭代中仍然可以使用。RETAIN语句的基本形式如下:
RETAIN 元素列表1 <初始值1 | 初始值列表1> <...元素列表n <初始n | 初始值列表n> >;
其中:
元素列表指定要在历次迭代中保持其值的变量名、变量列表或数组名。
初始值或初始值列表为其前面的元素指定的初值(为数字或字符)。当指定一个初始值时,该初始值被指定为其前面元素列表中的所有元素的初值。若指定的是初始值列表(多个初始值),SAS会将该列表中的第一个值指定给第一个元素,第二个值指定给第二个元素,依此类推。当未指定初始值或初始值列表时,其前面的元素的初始值为缺失值。
例3.22:基于数据集saslib.sales,使用RETAIN语句和赋值语句计算公司产品全年总销售额。
示例代码如下:

data work.sales_retain;
    set saslib.sales;
    retain Total_Sales 0;
    Total_Sales=Total_Sales+Sales;
    format Total_Sales DOLLAR10.;
run;

proc print data=work.sales_retain noobs;
run;

RETAIN语句将Total_Sales的初值设置为0,并告诉SAS在每次迭代中保持Total_Sales的值。接下来的赋值语句将上次迭代中计算得到的Total_Sales值与当前观测中Sales的值相加,结果存储在Total_Sales中。PRINT语句打印输出数据集的内容如图3.27所示。
该例使用的数据saslib.sales中变量Sales没有缺失值。如果Sales中存在缺失值,那么赋值语句中表达式(Total_Sales+Sales)的结果也为缺失值,这样会导致当前及其后所有迭代中Total_Sales的值都为缺失值。读者可在SET语句中使用例3.20中使用的带缺失值的数据集saslib.sales2,并查看其生成数据集的内容。当数据值中包含缺失值时,还可以使用SUM函数对变量求和,该函数只会计算非缺失值的和,具体的接下来会介绍。
此外,使用RETAIN语句还需要注意的是,如果该变量名仅在RETAIN语句中出现,并且RETAIN语句中未对其赋初值,则该变量不会写入输出数据集中。反之,如果RETAIN语句中给出了变量初始值,即使该变量仅在RETAIN语句中出现,该变量也会写入输出数据集。
4.?使用SUM函数
SUM函数返回非缺失值参数的和。SUM函数的基本形式如下:
SUM(参数, 参数...);
该求和语句等效于RETAIN语句和SUM函数的组合。其中,参数指定为数字常量、数字变量或数字表达式。如果参数中包含缺失值,且所有参数都是缺失值,则返回缺失值;若任一参数不是缺失值,则返回非缺失值参数的总和。与求和语句不同,SUM函数不会保持任何变量的值,所以如果要想保持的变量,应该使用RETAIN语句。
例3.23:基于数据集saslib.sales,计算公司产品全年总销售额。
示例代码如下:

data work.sales_sumfunc;
    set saslib.sales;
    retain Total_Sales 0;
    Total_Sales=sum(Total_Sales,Sales);
    format Total_Sales DOLLAR10.;
run;

所生成的数据集work.sales_sumfunc 的数据和例3.22一样。

上一篇:大数据项目缘何失败?分析模型需要与业务相结合


下一篇:CentOS常用命令