1 读取杂乱的原始数据(列指针+冒号修饰符)
当原始数据中没有排列整齐或无法预知要读取的字符长度时,三种输出样式及其混合都无法完成读取。这时就需要借助更多的工具:@'character'列指针 和 冒号修饰符。
列指针
列指针有两种用法:
- @n:n指SAS要移动到的列
- @'character':character指SAS要移动到的特定字符或者单词
@'character'列指针能在读取数据之前,将指针移动到指定的列。然而,有时候我们并不知道数据开始位置,若知道数据总是在一个特定的字符或者单词之后开始,这种情况就能使用@'character'列指针。
狗的品种信息总是出现在单词breed之后,示例:input @'breed:' dogbreed $;
冒号修饰符
字符变量的默认长度是8个字符。则读取变量时有几种可能情况:
- 字符变量长度 ≤ 8,读入语句运行良好
- 字符变量长度 > 8,只能读入长度 ≤ 8的数据,其他会丢失
- 若指定输出格式,如($20.),则读入变量可能会包含不需要的字符
为避免遇到上面问题,可以在输入格式使用冒号修饰符:在输入格式前面放置一个冒号。这样就能告知SAS读取到输入格式的长度 或 直到遇到分隔符就终止,二者以先遇到者为准。
示例::$20.
以变量值rottweiler为例,下表是几种不同input语句得到的结果:
input语句 | 描述 | 变量dogbreed的值 |
---|---|---|
input @'breed:' dogbreed $; | 默认字符变量长度为8个字符 | rottweil |
input @'breed:' dogbreed $20. ; | 指定字符变量长度为20个字符 | rottweiler vet bill |
input @'breed:' dogbreed :$20. ; | 冒号修饰符 | rottweiler |
2 为每个观测读取多行原始数据(行指针)
有的时候,一个观测的数据分散到了多行中,这时就需要显式告诉SAS何时换行,进入下一行继续读取。
行指针
在input语句中加入行指针,即可实现为单个观测读取多行原始数据。行指针有两种表示方法:
- 斜线(/):跳到下一个原始数据行,简单
- 井号n(#n):跳到指定行号的原始数据行,更灵活
示例:
input city $ state $
/ NormalHigh NormalLow
#3 RecordHigh RecordLow ;
3 从每行原始数据读取多个观测(双尾@)
无论数据以何种形态存在,总会经常出现这种情况,一行原始存在多个观测,这时需要在input语句结尾处使用双尾@符号。
双尾@
即(@@),其作用是让SAS停留在那行数据,继续读取观测直到数据读取完毕,或者遇到了没有双尾@符号的input语句为止。
示例:input city $ state $ NormalRain MeanDaysRain @@ ;
4 读取原始数据文件的一部分(单尾@)
当我们只需要读取一个比较大数据文件中的一小部分,这时就需要进行选择性读入,只读入需要的变量以确定是否保留当前的观测,然后用单尾@符号结束input语句。
单尾@
单尾@符号的作用是,告诉SAS保持那行原始数据。通常,在单尾@保持该数据行时,可以使用if语句来测试该观测,以查看它是否是你要保留的观测。如果是,你可以使用第二条input语句,为其余变量读取数据。
单尾@(@)和列指针(@n)非常相似,@n是告诉SAS移动到指定的列;而单尾@则像是在告知“敬请期待,请勿换台”,SAS将保持住该行数据直到data步结束,或者遇到一个没有单尾@的input语句为止。
示例:
input type $ @ ;
if type = 'surface' then delete ;
input name $ 9-38 amtraffic pmtraffic ;
这里有3条语句:
- 第一条input语句:读取字符变量type ,并保持该行数据
- if语句:对保持的数据进行测试
- 第二条input语句:读取name 、amtraffic 、pmtraffic 三个变量
运行逻辑是:若一个观测的type变量值是surface,则第二条input语句不会执行,这样就不会将不需要的观测添加到想要的数据集中取。
行固定标识符
单尾@和双尾@都是SAS中的行固定标识符。区别在于它们保持一行输入数据的时间长短不同。
- 单尾@:为后续的input语句保持一行数据,但是当SAS回到data步的顶部开始生成下一条观测时,它将释放那行数据
- 双尾@:即使在SAS开始生成新观测时,也为后续的input语句保持那行数据
两种的共同点是,当SAS遇到了没有行固定标识符的后续input语句时,改行数据都会被释放。