我们知道,在SAS的数据集里,对每个变量的属性都做了规定,变量类型、长度、输入格式、输出格式等等。
在这节中,我想分享一下关于在对变量的长度设定这一情况下,length语句和informat、format语句的区别。
首先阐述下length语句的SAS官方定义:
Specifies the number of bytes for storing variables.
关于informat语句的SAS官方定义:
Associates informats with variables.
关于format语句的SAS官方定义:
Associates formats with variables.
从定义来看,length是对变量存储长度的设定;informat是对变量输入格式的设定,format是对变量输出格式的设定。
我们可以直接通过日期格式来非常形象的解释这三者的区别,今天是2017年2月16日,以这个日期为例:
datatmp;
informatvar yymmdd8.;
formatvar yymmdd10.;
inputvar $;
var1 = var;
cards;
17-02-16
;
run;
运行打开结果数据集,同时对数据集右击选择列属性:
从上述结果看到日期的输入格式和输出格式,同时通过var1新变量,我们可以看到它的本质是一个数字20866,只是通过format格式展现为日期类型,由于是数值型,长度默认为8,因此我省去了length语句,var1只继承了它的变量长度属性和类型,并没有继承它的输入和输出格式。
当我们在对一个数据集的变量存储长度用length语句进行设定的时候,由于变量的输入格式并未进行设定,所以在通常的情况下变量的informat被默认为length语句下的输入格式,但是在数据的列属性里是看不到这一格式的,举个简单的例子如下:
datatmp;
lengthvar $3;
var = "abc";
run;
运行后点击数据集右键查看列属性:
最终我们看到变量的长度是3,输入格式和输出格式均为空。
而我们直接双击打开数据集,然后双击对应列,查看变量属性:
我们可以看到变量的长度为3,输入格式和输出格式都为$3.,类型为字符型。
那么接下来,我们对变量的informat进行设定,举个简单的例子如下所示:
datatmp;
informatvar $3.;
var = "abc";
run;
运行后对结果数据集进行右击选择列属性,如下所示:
我们看到变量的长度为3,输入格式则变成了$3.。
同理,对于format进行设定,我们也可以得到var的长度为3,输出格式变成$3.。
从上面两种不同的打开方式,我们看到两种不同的结果。
之所以出现两种不同的结果,我个人的观点认为前者所对应的是变量的初始化属性,而后者是变量默认的属性,当变量的输入和输出格式未初始化时,变量初始化为空,变量的默认属性为length语句设定的属性,当变量的输入和输出格式初始化时,变量的默认属性则就是初始化的属性。
之前在前一篇文章SAS中的informat和input,你真的拧得清吗?中,我讲到了关于length语句和informat语句的联系,那么接下来为了能够了解format的功能,我们举个简单的例子:
tmp1数据集采用format语句,tmp2数据集采用length语句,进行纵向合并得到tmp3:
datatmp1;
formatvar $3.;
var = "abc";
run;
datatmp2;
lengthvar $5;
var = "abcde";
run;那么在合并的时候,为了不出现截断问题,我们通常会通过使用length语句或者informat语句来进行长度的设定,如下所示:
datatmp3;
lengthvar $10;
settmp1 tmp2;
run;
最终得到如下的结果:
我们发现在设定var长度为10的情况下,最终的结果还是被截断了,第二行观测值‘abcde’被截断为‘abc’了。
为什么会出现这种情况呢,其实我们所看到的的结果是假的,var的值并没有被截断,只是受到了format语句的影响,我们右击数据集,选择列属性:
我们发现,变量var的输出格式为$3.,因此出现了上面那种被截断的假象。
为了证明这一点,做个简单的测试:
datatmp4;
settmp3;
var1 = var;
run;
通过新生成一个变量var1,var1无初始化输入和输出格式,因此我们可以看到真实的var的值,如下所示:
最终我们看到如上结果,var1的第二行观测值又恢复原值了。
为了避免这种情况,我们可以在length语句的前提下,加上format语句就可以了,如下所示:
datatmp3;
lengthvar $10;
formatvar $10.;
settmp1 tmp2;
run;
这样,我们就能得到如下结果:
上述这种情况在数据处理中其实很容易被我们忽略掉,大多数情况都是在我们使用import过程时,我们初始化了每个变量的informat和format格式,因此在后面处理这些变量时可能碰到这种类似的由于format语句而让你误以为数据产生了截断的情况,所以才有了这一节的提醒,希望能对各位有所帮助。