SAS数据导入input要点

时间:2024-10-30 07:29:38

1、input的输入格式

字符型变量默认8个字符,若使用input语句时,原文件字符长度超过8个字符,如果不加以说明,此时input会将字符截断为8个字符,如下:

  1. 代码1
  2. data a;
  3. input name $ age;
  4. cards;
  5. xiaomingd5 3
  6. xiaohong 4
  7. ;
  8. run;

此时第一个变量xiaomingd5将被截断,生成的结果为:

若使用input格式输入时,在$加上字符的长度,此时在读取时,就会按照指定的长度读取数据,将上面代码改为:

  1. 代码2
  2. data a;
  3. input name $9. age;
  4. cards;
  5. xiaomingd5 3
  6. xiaohong 4
  7. ;
  8. run;

此时第一个变量xiaomingd5的长度将会改变为9个字符,生成的结果为:

你会注意到name是改变了,但是两次的age结果不一样,这是为什么?

因为input语句总是从第1列开始读取数据,因此第一个变量name $9. 从第一列读到第9列,无论其中是否有分隔符。age变量的起始点在第10列,sas开始从第10列读取age之,所以代码2中age的值是5。

 

能否正确读取age值呢?可以的,使用冒号修饰符:

  1. 代码3
  2. data a;
  3. input name :$9. age;
  4. cards;
  5. xiaomingd5 3
  6. xiaohong 4
  7. ;
  8. run;

此时再运行程序,age值就是3。

【当一个变量的长度在input之前定义时,sas将一直读取直到遇到分隔符或者达到之前定义的长度为止】

  1. 代码4
  2. data a;
  3. informat name $9.;
  4. input name $ age;
  5. cards;
  6. xiaomingd5 3
  7. xiaohong 4
  8. ;
  9. run;

代码3和代码4的行为是一致的;

2、input中的指针

  • 在读取外部数据时,跳到指定列使用@n,告诉sas在读取数据之前将指针移动到第n列;

当你不知道数据开始位置,但是知道他总是在一个特定的字符后开始的,可以使用@‘character’指针,如:stu_name的数值总是出现在单词name后面,可以用下面的input语句

input @‘name’ stu_name $;
  • @@从一行中读取多个观测:input语句以@@结尾,就像停车标志一样告诉sas:“停下来,留在原始数据的当前行”。sas将停留在那行数据,继续读取观测直到数据读取完毕或者遇到了没有@@符合input语句为止。

  1. @@保持在本行:
  2. data c;
  3. input city $ state $ high low @@;
  4. cards;
  5. nome ak 55 44 miami fl 90
  6. 75 raleigh nc
  7. 88 68
  8. ;
  9. run;
  • +1代表跳过1列

  • 为每个观测读取多行原始数据:告诉sas何时跳到下一行,需要在input中添加行指针,斜线(/)和井号(#n)。在input语句中插入一个斜线(/)指示跳到下一个原始数据行,#n代表为该观测进入原始数据的第n行。

    1. data b;
    2. infile cards ;
    3. input city $ state $
    4. /high low
    5. #3 record weight;
    6. cards;
    7. nome ak
    8. 55 44
    9. 88 29
    10. miami fl
    11. 90 75
    12. 97 65
    13. raleigh nc
    14. 88 68
    15. 105 50
    16. ;

    斜线(/)告知sas在读取high和low前移动到数据下一行的第一列,#3告知sas在读取record和weight之前移动到数据第三行的第一列。

3、input语句中的冒号‘:’

从外部导入数据,有时会需要给每个变量赋予输入格式,主要有2种办法:

法1:使用informat语句

  1. data a;
  2. informat birth MMDDYY10.;
  3. input name $ age birth;
  4. datalines;
  5. hong 8 12/25/18
  6. bai 9 10/23/17
  7. lan 11 09/16/18
  8. ;
  9. run;

注:如果不指定输入格式,系统将不能识别birth里的数据格式,birth的运行结果将是数值型的缺失值;

法2:使用input中的冒号‘:’

  1. data a;
  2. input name $ age birth:MMDDYY10.;
  3. datalines;
  4. hong 8 12/25/18
  5. bai 9 10/23/17
  6. lan 11 09/16/18
  7. ;
  8. run;

输出结果如下: 

input语句中变量后跟数据格式时带冒号和不带冒号的区别:

带冒号指的是确定数据输入的格式,不带冒号如:birth MMDDYY10.指的是数据读取的位置,会导致读入数据不准确:

  1. data a;
  2. /* informat birth MMDDYY10.;*/
  3. input name $ birth MMDDYY8. age;
  4. format birth MMDDYY10.;
  5. datalines;
  6. hong 12/25/18 8
  7. bai 12/25/18 9
  8. lan 12/25/18 10
  9. ;
  10. run;

结果如下:

带冒号的运行结果:

  1. data a;
  2. /* informat birth MMDDYY10.;*/
  3. input name $ birth :MMDDYY8. age;
  4. format birth MMDDYY10.;
  5. datalines;
  6. hong 12/25/18 8
  7. bai 12/25/18 9
  8. lan 12/25/18 10
  9. ;
  10. run;

结果如下:

4、双input /单尾@/读取原始文件的一部分if input

不用读取所有数据再做筛选保留哪些数据,可以只读需要的变量以确定是否保留当前的观测,用@(单尾@)结束input语句。该符合告知sas保持那行原始数据。在单尾@保留行数据时,你可以用IF语句来判断该变量,看他是否需要保留。如果是,则用第二个input语句为其余变量读取数据。如果没有单尾@,sas将自动为每一个input语句读取下一行原始数据。

input与if else的结合:

  1. data a;
  2. infile datalines;
  3. input name $ @;
  4. total+age;
  5. if name='hong' or name='lan' then input age high;
  6. cards;
  7. hong 9 8
  8. hong 8 9
  9. lan 8 1
  10. lan 7 7
  11. bai 3 4
  12. bai 4 6
  13. ;
  14. run;

结果集:

  1. data a;
  2. infile datalines;
  3. input name $ @;
  4. total+age;
  5. if name='hong' or name='lan';
  6. input age high;
  7. cards;
  8. hong 9 8
  9. hong 8 9
  10. lan 8 1
  11. lan 7 7
  12. bai 3 4
  13. bai 4 6
  14. ;
  15. run;
  16. proc print data=a;
  17. run;

结果集:

【对比单尾@和双尾@@】

@和@@都是行保持符,区别在于他们保持一行输入数据的时间长短不同,单尾@为后续的input语句保持一行数据,当sas回到data步的顶部开始生成下一条观测时,他将释放那行数据。

双尾@@即使在sas开始生成新观测时,也为后续的input语句保持那行数据。

<T123例题7>、<T123例题13>