在SAS中附加多个CSV文件

时间:2013-09-25 17:21:25

标签: csv sas

我需要在一个SAS数据集中导入大量的csv文件。它们都具有相同的数据结构(相同的变量,第一行的变量名称)。我通常在SQL工作,但我被迫参加SAS中的这个特殊项目,我只掌握基本知识。

目前,我的代码如下所示:

proc import out=work.data
   datafile = file1.csv
   DBMS=CSV REPLACE;
   GETNAMES=YES;
   DATAROW=2;

proc import out=work.newData
   datafile = file2.csv
   DBMS=CSV REPLACE;
   GETNAMES=YES;
   DATAROW=2;

proc append base=work.data 
            data=work.newData force;    
run;

以及file3.csv ... file4.csv。

等等

我确信,有一种更优雅的方法,即在一个文件夹上循环所有csv文件而不显式写入它们(有几千个文件)。

感谢您的帮助。

5 个答案:

答案 0 :(得分:4)

你需要找出输入语句,而不是使用PROC IMPORT(虽然如果你使用PROC IMPORT一次,它会礼貌地将输入代码写入你可以使用的日志中),然后你可以使用通配符:

data mydata;
infile "c:\temp\*.csv" dlm=',' missover lrecl=32767;
input
myvar1
myvar2 $
myvar3
myvar4 :date9.
;
run;

存在其他一些选择;例如,请参阅https://communities.sas.com/message/182012#182012了解其他方法。

答案 1 :(得分:2)

import过程接受filename语句创建的fileref,filename语句接受多个文件。因此,您可以执行以下操作:

filename csvs ('file1.csv', 'file2.csv', 'file3.csv', 'file4.csv');

proc import out=work.data
datafile = csvs
DBMS=CSV REPLACE;
GETNAMES=YES;
DATAROW=2;
run;

我不完全确定这对于多个csv是如何工作的,每个csv都有一个标题,但我似乎记得SAS识别每个新文件并按照DATAROW=2语句跳过第一行。

或者您可以使用宏来循环文件夹中的所有文件,导入它们,然后将它们附加到主集。 This answer here应该可以帮助您获取文件夹中所有文件的列表。然后你可以做类似的事情:

%macro importcsvs (folder, outputname);
    /* I assume this is your macro that takes a folder and returns a dataset */
    /* (called filelist) containing the filename in variable: file */
    %getallfilesinfolder(&folder, filelist);

    /* determine number of files to read */
    %let numfiles=0;
    data _null_;
    set filelist end=last;
    if last then call symput('numfiles',put(_n_,best.));
    run;

    %do i=1 %to &numfiles;
        %let curfile=;
        data _null_;
        /* obs and firstobs =i mean you only read item i in the dataset */
        set filelist (obs=&i firstobs=&i); 
        call symput('curfile',file);
        run;

        filename csv "&curfile";
        proc import out=work.data
        datafile = csv
        DBMS=CSV REPLACE;
        GETNAMES=YES;
        DATAROW=2;
        run;

        data work.&outputname;
        set
        %if %sysfunc(exist(work.&outputname)) %then %do;
             work.&outputname
        %end;
             work.data;
        run;
    %end;

%mend;

%importcsvs(/your/folder/with/csvs, newData);

答案 2 :(得分:2)

为了扩展Joe的答案 - 这是一个如何导入多个CSV文件的示例,所有这些文件都包含标题行:

  • 在一个数据步骤中
  • 每次SAS处理标题行时都不会在日志中生成注释或错误
  • 不包括生成的SAS数据集中的任何标题行

代码:

/*First make a few CSV files to import*/

%macro generate_csvs(n);
    %do i = 1 %to &n;
        proc export
            data = sashelp.class 
            dbms = csv 
            outfile = "C:\temp\class&n..csv";
        run;
    %end;
%mend generate_csvs;

%generate_csvs(2);

/*Import the CSV files*/

data want;
    length _filename_ $32;
    infile "c:\temp\class*.csv" dlm = ',' filename = _filename_;
    input @;
    if _filename_ ne lag1(_filename_) then delete;
    input name :$8. sex :$1. age :8. height :8. weight :8.;
run;

注意:

    在li尝试读取文件末尾之前,
  • _filename_未更新 - input @;在没有实际输入任何数据的情况下触发此操作,同时保留第二个{{1}的当前行非标题行的语句。
  • input未包含在输出数据集中,但如果要跟踪每个记录来自哪个csv,则可以轻松地创建另一个变量作为其副本。
  • _filename_格式修饰符允许输入语句读取不在固定宽度列中的格式化变量。

答案 3 :(得分:1)

将所有文件复制到一个文件夹中,并将其更改为sas中的当前文件夹

x 'cd C:\Users\csvfolder';/*Your-folder-path*/

filename csv ('*.csv');

proc import out=work.allcsv
datafile = csv DBMS=CSV REPLACE;
GETNAMES=yes;
run;

答案 4 :(得分:0)

SAS宏语言中的循环方法应该有效。例如:

%macro loops(data);

data test;infile "c:\folder\&&data..csv" dsd missover lrecl=xyz dlm=
           firstobs=  and so on;
input var1-var20;
run;

proc append data=test base=AllCSVFiles;
run;

%mend;
%loops(csvdatafile)
%loops(etc...)

这是非常通用的代码。如果您可以创建仅包含csv数据文件名称的文件,则可以在新宏中调用%loops:

data files;infile 'c:\folder\FileWithCsvDataFileNames' options as above;
length csvfilename $32.;
input csvfilename;
run;

%macro callmacro;

data _null_;set files nobs=nobs;
call symput('TotFiles',put(nobs,8.));
run;

%do a=1 %to &&TotFiles;

data _null_;set files;
if _n_=&&a;
call symputx('csvdatafilex',put(csvfilename,$32.));
run;

%loops(&&csvdatafilex)

%end;

%mend;
%callmacro