5

我需要在一个 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 文件而不显式编写它们(有几千个文件)。

谢谢你的帮助。

4

5 回答 5

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了解其他方法。

于 2013-09-25T17:31:50.907 回答
2

import过程接受由filename语句创建的文件引用,并且该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声明跳过第一行。

或者,您可以使用宏循环遍历文件夹中的所有文件,导入它们,并将它们附加到您的主集中。这里的答案应该可以帮助您获取文件夹中所有文件的列表。然后您可以执行以下操作:

%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);
于 2013-09-26T21:35:22.337 回答
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;

笔记:

  • _filename_在 SAS 尝试读取文件末尾之后才会更新 -input @;在没有实际输入任何数据的情况下触发此操作,同时input为非标题行的第二个语句保留当前行。
  • _filename_不包含在输出数据集中,但如果您想跟踪每条记录来自哪个 csv,您可以轻松地创建另一个变量作为其副本。
  • :格式修饰符允许输入语句读取不在固定宽度列中的格式化变量。
于 2014-10-22T22:11:17.613 回答
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;
于 2014-03-05T10:21:43.990 回答
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
于 2015-05-27T12:48:32.530 回答