1.简单举例,假设我有4个TXT文件,每个文件中1个数值变量,共5个观测(如12345),数据分析前,需要先用循环语句对这几个文件的数据预处理,我现在的问题在于怎么用SAS语句读取文件,以前做的分析全用VB程序编的:1.例如,VB语句可以这样写:Fori=1to4open“E:”&i&“.txt”forInputAs1WhileNotEOF(1)Input#1,ba(m)=bm=m+1WendClose1Nexti2.尝试用SAS语句:dataa;doi=1to4by1;infile“E:”i“.txt”;end;inputv;run;———问题:SAS语句在“Infile”那行的“i”处提示错误,数据读不进去……请问SAS语句中有什么方法可以实现以上用途吗?——–请各位高手不吝相助,不胜感激~~~hopewell答案:datatemp;doin=1to4;fname=cats(‘d:’,in,’.txt’);dountil(last);infileXXXfilevar=fnameend=last;inputv;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。BecauseSASdoesnotdetectanend-of-filewiththisaccessmethod,youmustincludeprogramstatementstopreventcontinuousprocessingoftheDATAstep.在这里提出一个思路:我们在解决这类问题的时候,先考虑是一个文件的时候,你如何写程序,如何读取,如果是两个文件的时候,程序与读取一个文件时程序有什么不同,这种不同是什么原因导致,这个不同是否有规律可循,寻找到规律你就有思路了.2.sql应用原程序和解答在这里,想分解一下答案程序dataa;inputnbrcode;datalines;13900000000101023451390000000010102346139000000001010234713900000000101023481390000000110102345139000000011010234613900000001101023491390000000210102345139000000021010234713900000002101023491390000000310102345139000000031010234613900000003101023481390000000310102349;run;procsql;createtablebasselecta.codeasprom_1,b.codeasprom_2,count(distincta.nbr)asCsr_Cntfromaainnerjoinabona.codeb.codeanda.nbr=b.nbrgroupbya.code,b.code;quit;首先soporaeternus哥们的SQL确实很不错,学SQL,可以看看他的程序,学习的地方太多了。对于这个程序思路如下:首先利用在SQL中的同一个数据集不同的别名,克隆另外一个相同的数据集,利用ON语句中条件,以及INNERJOIN进行CODE的组合,这个是解决问题的关键,先形成组合。因为不同NBR的CODE组合,有些相同,有些不相同,于是用GROUPBY来排除重复的组合,保证组合的唯一性,为后面计算NBR提供正确唯一的组合。因为不同的NBR可能存在相同的CODE组合,反过来,同一个的CODE组合存在不同的NBR,因为我们计算的是NBR的个数,因此我们在GROUPBY限定了CODE组合的唯一性,然后利用COUNT函数来计算NBR的个数,思路就是这样,想起来其实也不难,关键是面对数据的时候要快速的理清思路很关键。这里指的学习是:克隆相同的数据集,GROUPBY保证CODE组合的唯一不重复.3.sql中宏变量的赋值dataa2;num=0;do_n_=1by1until(last._col0);seta1;by_col0;num+1;output;end;run;procsql;selectmax(num)into:obsfroma2;quit;%macroaa();dataa3;doi=1by1until(last._col0);seta1;by_col0;arraym(*)m1-m%left(&obs.);m(i)=rate3_change;end;dropirate3_change;run;%mend;%aa;这个哥们先后用转置和数据实现了按照要求读入数据并实现既定的数据集格式先分析这个哥们的程序:1.建立数据集A1,并进行排序,为后面的SET做一个准备2.在建立数据集A2的时候,设置一个变量NUM,这个变量是表示有每一_COLO重复的次数,这个很关键,因为后面就是根据重复的次数来设置数组的。3.将每一个_COLO重复的次数的变量NUM,用SQL赋值给一个宏变量,然后作为数组的界值,而且随着_n_的不同,引起的NUM不同,导致数组的界值不同,因为相同的_COLO的rate3_change能在一个观测里体现出来。这个里面最关键的是寻找宏循环中数组的界值与_COLO重复次数,用了一个NUM和宏变量&obs.值得学习的一点.4.datastep及宏调用在这里提供了两个循环调用宏的方法,一个是用另外一个宏循环调用外部的已经编写好的宏另外一个是在data步里面调用宏。%macroouter;%doi=1%to10;%inner2(0,1,&i);%end;%mend;%outer这个是第一个方法,其实这个方法我最熟悉也经常用的一个方法,封装在另外一个宏循环里面,结构清晰,不容易出错。其实在这里给我们写程序提供了一个思路,对于一个比较复杂的程序来说,我们要学会功能分解,结构化的去设计程序。例如在这个程序里面,我们讲重复需要实现的过程或者步骤写成一个宏程序,设置好宏参数。解决一个比较复杂问题的时候,将问题分解成若干个小问题,对于每一个问题或者每一个功能写成一个宏模块,但是一定要设计好参数,这个参数是与其他结构模块相互沟通的接口。就想现在建房子一样,都是组合式,每一个部门都是标准化设计,然后组合在一起实现一个整体的需要或者整体的功能。hopewell的程序里面提供一个宏宇data步交互的方法%macroinner(x,y,z);%putNOTE:***Macroinner:x=&xy=&yz=&z***;%mendinner;data_null_;doi=1to3;callexecute(cats(‘%inner(0,1,’,put(i,best.),’)'));/*%inner(0,1,i);*/end;run;其实要说难理解应该是callexecute(cats(‘%inner(0,1,’,put(i,best.),’)'));其实这句话里面cats连接字符函数,最后得出的结果其实就是callexecute(‘%inner(0,1,i)’)但是在这里如果直接写callexecute(‘%inner(0,1,i)’)岂不是更简洁?如果说是没有参数,callexecute(‘%inner’)这样是可以的,但是如果是参数,就注意,如果写成callexecute(‘%inner(0,1,i)’),他会解析成一个宏调用,%inner(0,1,i),同时DATA步停止,而不是我们想的%inner(0,1,1)这样,因此要想得到%inner(0,1,1)这样解析结果,就要对I进行一个处理,把%inner(0,1,1)看做一个字符串,对于这个字符串变化的那个需要用put函数将其转换一个字符,用cats来连接。至于callexecute的使用方法:可以看看下面一个我转载的帖子[功能]解析参数,如果解析后的值是sas语句(sasstatement),则在下一个步边界(stepboundary)执行;如果此值为macro语言元素(macrolanguageelement),则立即执行.用于在datastep中与macro机制进行交互.[分类]宏(macro)[语法]CALLEXECUTE(argument);[参数]argument指定一个产生宏调用或者sas语句的字符表达式或者常量.argument可以是:一个字符串,放入引号内data步的字符变量,不要使用引号括住一个字符表达式,数据步解析成宏文本表达式(macrotextexpression)或者sas语句.[详细]如果参数被解析成一个宏调用,则宏立刻运行,在这个宏执行时,data步的执行暂停.如果参数被解释成一个sas语句,或者宏的执行产生sas语句,这些语句在callexecute子程序的所在的data步结束后才执行.[CALLEXECUTE子程序同步(timing)详解]当想有条件的执行macro时,CALLEXECUTE很有用.但牢记,如果callexecute产生macrolanguageelements,则他们立即执行;如果callexecute产生saslanguagestatements,或者macrolanguageelements产生saslanguagestatements,这些statements在当前datastep执行后执行.下面两个例子阐述用户使用callexecute常有的问题例1:dataprices;/*IDforpricecategoryandactualprice*/inputcodeamount;cards;56300991000024225;%macroitems;%globalspecial;%letspecial=football;%menditems;datasales;/*incorrectusage*/setprices;lengthsaleitem$20;callexecute(’%items’);saleitem=”&special”;run;在DATASALESstep中,在data步编译时,对SALEITEM的赋值需要macro变量SPECIAL的值.但是直到datastep执行时,callexecute才产生这个值.所以,在log中能看一个未解析宏变量的消息,并且SALEITEM的值为&special.在这个例子中,去掉宏定义或者把DATASALES步放到宏ITEMS中更好.在这两种情况下,callexecute都不必要,也没什么用处.下面是此程序正确的一个版本dataprices;/*IDforpricecategoryandactualprice*/inputcodeamount;cards;56300991000024225;%letspecial=football;/*correctusage*/datasales;setprices;lengthsaleitem$20;saleitem=”&special”;run;例2:/*Thisversionoftheexampleshowstheproblem.*/dataprices;/*IDforpricecategoryandactualprice*/inputcodeamount;cards;56300991000024225;dataname