我需要在一个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文件而不显式写入它们(有几千个文件)。
感谢您的帮助。
答案 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文件的示例,所有这些文件都包含标题行:
代码:
/*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_
未更新 - 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