全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 SAS专版
2010-8-19 23:25:02

跟crackman读SAS程序(1)

初学SAS,请教各位高手一小问题,关于循环语句中读取数据文件,如下:

简单举例,假设我有4个TXT文件,每个文件中1个数值变量,共5个观测(如1 2 3 4 5),数据分析前,需要先用循环语句对这几个文件的数据预处理,
我现在的问题在于怎么用SAS语句读取文件,以前做的分析全用VB程序编的:

1.例如,VB语句可以这样写:
For i=1 to 4
       open "E:\" & i & ".txt" for Input As 1
       While Not EOF(1)
                Input #1, b
                a(m) = b
                m = m + 1
        Wend
        Close 1
Next i

2.尝试用SAS语句:
data a;
      do i=1 to 4 by 1;
           infile "E:\" i ".txt";
      end;
      input v ;
run;

---------问题:SAS语句在“Infile”那行的“i”处提示错误,数据读不进去......请问SAS语句中有什么方法可以实现以上用途吗?

--------请各位高手不吝相助,不胜感激~~~



hopewell答案:
data temp;
        do in=1 to 4;
                fname=cats('d:\',in,'.txt');
                do until(last);
                        infile XXX filevar=fname end=last;
                        input v;
                        output;
                end;
        end;
      stop;
run;

此处注意几点:
1.DO循环:很巧妙的注意到了D盘下TXT文件名的规律性,都是一个数字命名的文件名,用变量IN,采用CATS字符串连接函数,循环创建D盘下的TXT文件名变量FNAME;
2.在读取文本数据时,很多人都知道用INFILE,以及INFILE基本参数,XXX是文件名,filevar是打开或者关闭指定的文件名,end=last是定义一个变量了解是否读到文件的结尾处,这里的LAST与until里面的last保持一致
3.STOP,这里为什么用STOP,这个很重要,如果你去掉STOP,那么你会发现无线循环下去。所以当我们在DATA步里面制定读取的数据是以随机方式读取的时候,例如这个里面的IN,或者是在SET里面的POINT等,需要用STOP。Because SAS does not detect an end-of-file with this access method, you must include program statements to prevent continuous processing of the DATA step.


在这里提出一个思路:我们在解决这类问题的时候,先考虑是一个文件的时候,你如何写程序,如何读取,如果是两个文件的时候,程序与读取一个文件时程序有什么不同,这种不同是什么原因导致,这个不同是否有规律可循,寻找到规律你就有思路了。




二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2010-8-20 00:28:07

跟crackman读SAS程序(2)

http://www.pinggu.org/bbs/thread-888994-1-1.html
原程序和解答在这里,想分解一下答案程序
data a;
        input nbr code;
        datalines;
        13900000000 10102345
13900000000 10102346
13900000000 10102347
13900000000 10102348
13900000001 10102345
13900000001 10102346
13900000001 10102349
13900000002 10102345
13900000002 10102347
13900000002 10102349
13900000003 10102345
13900000003 10102346
13900000003 10102348
13900000003 10102349
;

run;
proc sql;
        create table b as
                select
                        a.code as prom_1
                        ,b.code as prom_2
                        ,count(distinct a.nbr) as Csr_Cnt
                from a a
                inner join a b
                on a.code<b.code
                        and a.nbr=b.nbr
                group by
                a.code
                ,b.code
        ;
quit;


首先soporaeternus 哥们的SQL确实很不错,学SQL,可以看看他的程序,学习的地方太多了。
对于这个程序思路如下:
首先利用在SQL中的同一个数据集不同的别名,克隆另外一个相同的数据集,利用ON语句中条件,以及INNER JOIN进行CODE的组合,这个是解决问题的关键,先形成组合。因为不同NBR的CODE组合,有些相同,有些不相同,于是用GROUP BY 来排除重复的组合,保证组合的唯一性,为后面计算NBR提供正确唯一的组合。因为不同的NBR可能存在相同的CODE组合,反过来,同一个的CODE组合存在不同的NBR,因为我们计算的是NBR的个数,因此我们在GROUP BY 限定了CODE组合的唯一性,然后利用COUNT函数来计算NBR的个数,思路就是这样,想起来其实也不难,关键是面对数据的时候要快速的理清思路很关键。这里指的学习是:克隆相同的数据集,GROUP BY 保证CODE组合的唯一不重复。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2010-8-20 00:32:01
顺便转一个对INNER JOIN LEFT JOIN RIGHT JOIN的介绍的帖子

sql之left join、right join、inner join的区别
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录
inner join(等值连接) 只返回两个表中联结字段相等的行

举例如下:
--------------------------------------------
表A记录如下:
aID     aNum
1     a20050111
2     a20050112
3     a20050113
4     a20050114
5     a20050115

表B记录如下:
bID     bName
1     2006032401
2     2006032402
3     2006032403
4     2006032404
8     2006032408

--------------------------------------------
1.left join
sql语句如下:
select * from A
left join B
on A.aID = B.bID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404
5     a20050115    NULL     NULL

(所影响的行数为 5 行)
结果说明:
left join是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的.
换句话说,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID).
B表记录不足的地方均为NULL.
--------------------------------------------
2.right join
sql语句如下:
select * from A
right join B
on A.aID = B.bID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404
NULL     NULL     8     2006032408

(所影响的行数为 5 行)
结果说明:
仔细观察一下,就会发现,和left join的结果刚好相反,这次是以右表(B)为基础的,A表不足的地方用NULL填充.
--------------------------------------------
3.inner join
sql语句如下:
select * from A
innerjoin B
on A.aID = B.bID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404

结果说明:
很明显,这里只显示出了 A.aID = B.bID的记录.这说明inner join并不以谁为基础,它只显示符合条件的记录.
--------------------------------------------
注:
LEFT JOIN操作用于在任何的 FROM 子句中,组合来源表的记录。使用 LEFT JOIN 运算来创建一个左边外部联接。左边外部联接将包含了从第一个(左边)开始的两个表中的全部记录,即使在第二个(右边)表中并没有相符值的记录。

语法:FROM table1 LEFT JOIN table2 ON table1.field1 compopr table2.field2

说明:table1, table2参数用于指定要将记录组合的表的名称。
field1, field2参数指定被联接的字段的名称。且这些字段必须有相同的数据类型及包含相同类型的数据,但它们不需要有相同的名称。
compopr参数指定关系比较运算符:"=", "<", ">", "<=", ">=" 或 "<>"。
如果在INNER JOIN操作中要联接包含Memo 数据类型或 OLE Object 数据类型数据的字段,将会发生错误.
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2010-8-20 08:05:02
谢谢楼主对程序的详尽解释,很受用。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2010-8-20 08:28:45
膜拜!!!!
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2010-8-20 08:52:34
楼主好热心呀!
infile语句的XXX好像只是个占位符,除了在log里露了个小脸之外,不起实际作用的
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

点击查看更多内容…
相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群