performance - SAS: Mejora de la velocidad de un bucle do con importación de proceso
do-loops (1)
Tengo más de 3400 archivos CSV, con un tamaño que varía entre 10kb y 3mb. Cada archivo CSV tiene este nombre de archivo genérico: stockticker-Ret.csv
donde stockticker
es el ticker de acciones como AAPL, GOOG, YHOO, y así sucesivamente y tiene devoluciones de acciones para cada minuto en un día determinado. Mi código SAS primero comienza al cargar todos los nombres de los stockticker-Ret.csv
archivo stockticker-Ret.csv
en un conjunto de datos SAS. Paso sobre cada teletipo para cargar el archivo .csv
apropiado en un conjunto de datos SAS llamado want
y aplico algunos pasos de datos en want
y almaceno el conjunto de datos final que want
de cada teletipo en un conjunto de datos SAS llamado global
. Como se puede imaginar, este proceso lleva mucho tiempo. ¿Hay alguna manera de mejorar mi código DO LOOP
continuación para que este proceso sea más rápido?
/*Record in a sas dataset all the csv file name to extract the stock ticker*/
data yfiles;
keep filename;
length fref $8 filename $80;
rc = filename(fref, ''F:/data/');
if rc = 0 then do; did = dopen(fref);
rc = filename(fref); end; else do; length msg $200.; msg = sysmsg(); put msg=; did = .; end;
if did <= 0 then putlog ''ERR'' ''OR: Unable to open directory.'';
dnum = dnum(did);
do i = 1 to dnum; filename = dread(did, i); /* If this entry is a file, then output. */ fid = mopen(did, filename); if fid > 0 then output; end;
rc = dclose(did);
run;
/*store in yfiles all the stock tickers*/
data yfiles(drop=filename1 rename=(filename1=stock));
set yfiles;
filename1=tranwrd(filename,''-Ret.csv'','''');
run;
proc sql noprint;
select stock into :name separated by ''*'' from work.yfiles;
%let count2 = &sqlobs;
quit;
*Create the template of the desired GLOBAL SAS dataset;
proc sql;
create table global
(stock char(8), time_gap num(5), avg_ret num(5));
quit;
proc sql;
insert into global
(stock, time_gap,avg_ret)
values('''',0,0);
quit;
%macro y1;
%do i = 1 %to &count2;
%let j = %scan(&name,&i,*);
proc import out = want datafile="F:/data/&j-Ret.csv"
dbms=csv replace;
getnames = yes;
run;
data want;
set want; ....
....[Here I do 5 Datasteps on the WANT sasfile]
/*Store the want file in a global SAS dataset that will contain all the stock tickers from the want file*/
data global;
set global want; run;
%end;
%mend y1;
%y1()
Como puede ver, el conjunto de datos SAS global se expande para cada conjunto de datos que want
almacenar en global
.
Suponiendo que los archivos tienen un diseño común, no debe importarlos con PROC IMPORT
o hacer bucles. Deberías leerlos todos con un solo paso. ES DECIR:
data want;
length the_file $500;
infile "f:/data/*.csv" dlm='','' lrecl=32767 dsd truncover firstobs=2 filename=the_file;
input
myvar1 myvar2 myvar3 myvar4;
stock_ticker=scan(the_file,''/',-1); *or whatever gets you the ticker name;
run;
Ahora, si no tienen diseños idénticos, o si hay alguna complejidad para la lectura, puede necesitar una declaración de entrada más compleja que eso, pero casi siempre puede lograrlo de esta manera. Los bucles con muchas IMPORTACIONES de PROC siempre serán ineficientes debido a la sobrecarga de la IMPORTACIÓN.
Si no desea que todos los archivos .csv estén en la carpeta (y no puede escribir una máscara para lo que desea), o si tiene un subconjunto de diseños, puede usar la opción FILEVAR para leer los archivos desde una conjunto de datos común Luego, si es necesario, podría dividir en varias declaraciones de entrada.
data want;
set yfiles;
infile a filevar=filename;
if filevar [some rule] then do;
input ... ;
end
;else if ... then do;
input ... ;
end;
run;