Reputation: 109
I recently found out about the filevar statement. Is it possible to use this to write various text files split by multiple variables? All the examples i've seen online have only written to text files based on a single variable they want to split by.
For example: Suppose I have a dataset about cars that contains a character variable about the color, a character variable detailing the make of car, and a numeric variable detailing the year of purchase.
Could I then use filevar to write multiple text files split by all of these variables at once (possibly by concatenation of them within a filepath and then set this filepath as a fileref)? So i'd get one text file that has make= A, color=Red, year=2000. A second text file that has make=A, color=Blue, year= 2000 etc.
Also i keep seeing the word fileref but no clear explanation of what is actually is. Intuitvely I get the feeling that it is just an alias for the name of a file that we can refer to in code?
Thanks.
Upvotes: 0
Views: 590
Reputation: 51621
I think you are talking about the FILEVAR=
option on the FILE
statement. This tells SAS to use the value of a particular variable to find the name of the file to write into. You can build it from anything you want.
A fileref
is the alias that you create when you use the FILENAME
statement or FILENAME()
function. Just like a libref
is the alias that you create when you use the LIBNAME
statement or LIBNAME()
function.
So you can define a fileref that points to one or more files.
filename file1 '/project1/source.csv';
filename file2 ('/project1/source1.txt' '/project1/source2.txt');
And then you can use the fileref in places you might have previously used a quoted physical filename.
infile file1 dsd ;
infile file2 eov=eov ;
You can also use fileref's to point to directories.
filename raw '/project1/' ;
And then add ()
to reference specific files within those directories.
infile raw('source.csv') dsd ;
infile raw('source1.txt' 'source2.txt') eov=eov;
file raw('export.csv') dsd ;
Upvotes: 0
Reputation: 63434
You're absolutely right; you can use filevar
to define the filename based on the data in your dataset.
Here's a trivial example, using sashelp.cars
to make a set of files, one per car make.
filename a temp;
data _null_;
set sashelp.cars;
outname = cats('c:\temp\',make,'.txt');
file a filevar=outname dlm=',';
put make $ model $ mpg_city mpg_highway;
run;
The a
filename is a junk filename - it is there because it has to have something in that spot in the syntax. It doesn't do anything (hence the temp
).
Things to note: using this method, you have to have a file sorted properly (in groups that correspond to your files). Otherwise it will not work the way you want it to. It doesn't have to be in order by that variable, but it has to be arranged by that variable. So this is fine:
A
A
B
B
G
G
C
C
D
D
But not this:
A
B
G
C
D
A
B
G
C
D
You also have to make sure you have legal filenames (so don't use model
in sashelp.cars
unless you clean it up, as it has lots of illegal characters like \
in it).
Upvotes: 1
Reputation: 12465
You can think of the fileref
as the pointer to the file, ala C/C++.
You absolutely can drive file output using the values from a data set. Here is an example using the first few observations from the SASHELP.CARS
data.
proc sort data=sashelp.cars (where=(make in ('Acura', 'Audi', 'BMW')))
out=cars;
by make type;
run;
data _null_;
set cars;
by make type;
retain fid;
if first.type then do;
f_name = catt("c:\temp\",make,"_",type,".txt");
rc = filename("temp",f_name);
fid= fopen("temp","o");
rc = fput(fid,'make,model,type,msrp');
rc = fappend(fid);
end;
rc = fput(fid,catx(",",make,model,type,msrp));
rc = fappend(fid);
if last.type then do;
rc = fclose(fid);
end;
run;
This generates a CSV file for each MAKE, TYPE
group listing the car name and MSRP.
For each group:
f_name
is the physical file name for the output. the filename()
and fopen()
functions open the file for output. fid
is the
reference to the file. fput()
puts a line into the buffer. fappend()
appends the buffer to the file. Do this for the header
and then once for each record. fclose()
Upvotes: 1