使用外部描述文件将固定列数据输入SAS

使用外部描述文件将固定列数据输入SAS,sas,Sas,我正在尝试将尼尔森克拉利塔的数据输入到SAS中,SAS采用固定列格式。看起来只有不到1000个变量。每个.dat文件都包含描述性文本文件。我想可能有一种方法可以利用这个描述性的txt文件来指定输入长度、名称、格式等等。有人能给我一个最简单的方法吗 经过几个小时的搜索,我找不到任何固定函数,我的最佳猜测是用do循环重新格式化描述性txt文件。如果这些程序中的任何一个能够提供更简单的方法,我也可以使用R、Stata和SAS Enterprise guide,并有使用这些程序的经验 这是描述性文件的一

我正在尝试将尼尔森克拉利塔的数据输入到SAS中,SAS采用固定列格式。看起来只有不到1000个变量。每个.dat文件都包含描述性文本文件。我想可能有一种方法可以利用这个描述性的txt文件来指定输入长度、名称、格式等等。有人能给我一个最简单的方法吗

经过几个小时的搜索,我找不到任何固定函数,我的最佳猜测是用do循环重新格式化描述性txt文件。如果这些程序中的任何一个能够提供更简单的方法,我也可以使用R、Stata和SAS Enterprise guide,并有使用这些程序的经验

这是描述性文件的一个示例:

RECORD LAYOUT: 2013.1 Pop-Facts Premier (2000) Data   (ZIP Codes Level)

POSITION     TYPE SIZE  CONTENTS

    1-    2   A    2    Record Type
    3-    4   A    2    FIPS State Code
    5-    7   A    3    FIPS County Code
    8-   12   A    5    FIPS Minor Civil Division (MCD) Code
   13-   18   A    6    Census Tract Code
   19-   19   A    1    Census Block Group (BG) Code
   20-   23   A    4    Metropolitan Statistical Area or New England County     
                        Metro Area (MSA/NECMA) Code                             
   24-   28   A    5    Core Based Statistical Area Code
   29-   33   A    5    ZipCode
   34-   38   A    5    FIPS Place Code
   39-   41   A    3    Designated Marketing Area (DMA) Code
   42-   43   A    2    Congressional District Code
   44-   63   A   20    State Name
   64-   95   A   32    County Name
   96-  145   A   50    Core Based Statistical Area Name
  146-  177   A   32    Geography Name
  178-  192   A   15    Geography Code (Concatenated Geography Code)
  193-  202   F 10.6    Latitude
  203-  213   F 11.6    Longitude

                        2000 Population by Single Race and Sex

  337-  345   I    9    2000 Population, White Alone
  346-  354   I    9    2000 Population, White Alone, Male
  355-  363   I    9    2000 Population, White Alone, Female
  364-  372   I    9    2000 Population, Black/African American Alone
  373-  381   I    9    2000 Population, Black/African American Alone, Male
  382-  390   I    9    2000 Population, Black/African American Alone, Female
  391-  399   I    9    2000 Population, American Indian/Alaskan Native Alone
  400-  408   I    9    2000 Population, American Indian/Alaskan Native Alone,  
                        Male                                                    
  409-  417   I    9    2000 Population, American Indian/Alaskan Native Alone,  
                        Female                                                  
  418-  426   I    9    2000 Population, Asian Alone
  427-  435   I    9    2000 Population, Asian Alone, Male
  436-  444   I    9    2000 Population, Asian Alone, Female
  445-  453   I    9    2000 Population, Native Hawaiian/Pacific Islander Alone
  454-  462   I    9    2000 Population, Native Hawaiian/Pacific Islander       
                        Alone, Male                                             
  463-  471   I    9    2000 Population, Native Hawaiian/Pacific Islander       
                        Alone, Female                                           
  472-  480   I    9    2000 Population, Some Other Race Alone
  481-  489   I    9    2000 Population, Some Other Race Alone, Male
  490-  498   I    9    2000 Population, Some Other Race Alone, Female
  499-  507   I    9    2000 Population, Two or More Races
  508-  516   I    9    2000 Population, Two or More Races, Male
  517-  525   I    9    2000 Population, Two or More Races, Female

通常,您需要创建一个如下所示的数据集:

colname | start | length | informat
其中informat至少包含$或不包含任何内容,并且可能包含一些关于它是否是日期/等的信息

然后您可以编写一个宏,如下所示:

%macro readincol(col,start,len,informat);
@&start. &col. &informat.$len..
%mend readincol;
然后将第一个数据集的行读入宏变量,如下所示:

proc sql;
  select cats('%readincol(',colname,',',start,',',length,',',informat,')') into :inputst
    separated by ' ' from layout_dset;
quit;
现在,您已经构建了输入语句,可以在datastep中使用它:

data want;
infile "myfile.txt" lrecl=32767;
input
&inputst.
;
run;

您还可以根据数据、布局和所需结果分配格式等。

或者您可以在创建布局数据集后在一个数据步骤中完成,如Joe的回答中使用CALL EXECUTE:

data _null_;
call execute(
    "data want;
        infile 'myfile.txt' lrecl=32767;
        input");
do until(eof);
   set layout_dset end=eof;
   call execute(cats("@",start)||colname||" "||cats(informat,length,"."));
end;
call execute(";run;");
run;

听起来您想要生成SAS代码来读取描述性文本文件并创建SAS数据集。真的没有一个好方法告诉你怎么做;使用您提供的数据向您展示一个示例程序更容易

下面应该给你一个好的开始。注意,您的源代码描述没有提供和列名,所以我只使用了一个范围VARnnn。您需要为每个要处理的文件修改此程序,输入是一个文本文件,正如您所示;输出是另一个包含SAS程序的文本文件

还请注意,您没有提供读取任何日期或日期时间值的示例;如果这些存在于某个地方,您将需要进行适当的更改

下面是使用您提供的示例测试的代码:

data inputs(keep=input_stmt)
     vars(keep=attrib dslabel);

   length dslabel $60 input_stmt attrib $200;
   retain varnum 0 dslabel;
   infile 'c:\temp\table1.txt' truncover;

   input @;
   if _infile_ =: 'RECORD LAYOUT:' then do;
      dslabel = substr(_infile_,16);
      input ///; /* skip next 3 lines */
      delete;
      end;

   input @1 START $5. @7 END 5. @15 TYPE $1. @17 SIZE $4. @25 LABEL $80.;
   if START ne ' '; /* ignore blank and non-data lines */
   varnum + 1; /* Variable counter */

   varname = 'VAR' || put(varnum,z3.);
   select(TYPE);
      when( 'A' ) infmt = '$' || trim(SIZE) || '.'; 
      when( 'F' ) infmt = SIZE; 
      when( 'I' ) infmt = trim(SIZE) || '.';
      otherwise   infmt = '$' || trim(SIZE) || '.'; /* Read as character */
      end;

   attrib = 'ATTRIB ' || trim(varname) || ' INFORMAT='
         || trim(infmt) || " LABEL='" || trim(label) || "';";

   input_stmt = '@' || trim(start) || ' ' || trim(varname) || ' ' 
               || trim(infmt);
run;

data _null_;
   file 'c:\temp\read_table1.sas' new;
   set vars;
   if _n_ = 1 then
      put "data table1(label='" dslabel "');"; 
   put attrib;
run;

data _null_;
   file 'c:\temp\read_table1.sas' mod;
   set inputs end=eof;
   if _n_ = 1 then
      put 'input'; 
   put @5 input_stmt;
   if eof then put ';' / 'run;';
run;

是的,我不得不处理同样的数据。。。这不好玩。我一直在做的是复制文本文件中的所有数据,并使用文本到列(固定宽度的文本列)将它们粘贴到Excel的单元格A4中。然后我正在使用Excel中的语法修复该死的格式化

=IFA4,IFB5=,连接EC4和C5,C4


然后我一直在对数据进行排序,以消除空格。任何关于如何清理此数据或按原样将其导入SQL的想法都会有所帮助

您能否发布一个描述性文本文件的示例,以及您自己试图解决此问题的一些代码?你可能只需要一个简单的宏。是的,谢谢你,约翰。我已经编辑了原始文章以包含描述文件的示例。我还没有写过任何代码,因为如果有一个预先存在的屏蔽函数,重新设计轮子似乎效率低下。