data name
filename reference name "filename.csv"
infile filename.csv dlm=",";
run;
what is wrong with the code?How to create data set by the reference csv file
Place the filename statement before the DATA Step.
You will need an INPUT statement to read the data into variables,
or if the file has a header row use Proc IMPORT and the system will best guess the input needed.
Example 1
Presume file has no header row and there are 3 columns of numbers separated by commas
filename myfile 'mydatafile.csv';
data want;
infile myfile dsd dlm=',';
input x y z;
run;
Example 2
Presume there is a header row
filename myfile 'mydatafile.csv';
proc import file=myfile replace out=want dbms=csv;
run;
or
* columns expected are known;
filename myfile 'mydatafile.csv';
data want;
infile myfile dsd dlm=',' firstobs=2;
input x y z;
run;
NOTE
An INFILE statement can also directly refer to a file
...
INFILE "filename.csv" ... ;
...
Related
I have a SAS dataset, let us say
it has 4 columns A,B,C,D and the values
A = x
B = x
C = x
**D = x,y**
Here column D has two values inside a single column while converting it into CSV format it generates a new column with the value Y. How to avoid this and to convert SAS dataset into CSV file?
* get some test records in a file;
Data _null_;
file 'c:\tmp\test.txt' lrecl=80;
put '1,22,Hans Olsen,Denmark,333,4';
put '1111,2,Turner, Alfred,England,3333,4';
put '1,222,Horst Mayer,Germany,3,4444';
run;
* Read the file as a delimited file;
data test; infile 'c:\tmp\test.txt' dsd dlm=',' missover;
length v1 v2 8 v3 v4 $40 v5 v6 8;
input
'V1'n : ?? BEST5.
'V2'n : ?? BEST5.
'V3'n : $CHAR40.
'V4'n : $CHAR40.
'V5'n : ?? BEST5.
'V6'n : ?? BEST5.;
run;
* Read the file and write another file.
* If 6 delimiters and not 5, change the third to #;
data test2;
infile 'c:\tmp\test.txt' lrecl=80 truncover;
file 'c:\tmp\test2.txt' lrecl=80;
length rec $80;
drop pos len;
input rec $char80.;
if count(rec,',') = 6 then do;
call scan(rec,4,pos,len,',');
substr(rec,pos-1,1) = '','';
end;
put rec;
run;
* Read the new file as a delimited file;
data test2; infile 'c:\tmp\test2.txt' dsd dlm=',' missover;
length v1 v2 8 v3 v4 $40 v5 v6 8;
input
'V1'n : ?? BEST5.
'V2'n : ?? BEST5.
'V3'n : $CHAR40.
'V4'n : $CHAR40.
'V5'n : ?? BEST5.
'V6'n : ?? BEST5.;
run;
In this code, it add '#' but I want ',' itself in the output.
Could anyone please guide me to do that?
Thanks in advance!!
It sounds like you are starting with an improperly created CSV file.
1,22,Hans Olsen,Denmark,333,4
1111,2,Turner, Alfred,England,3333,4
1,222,Horst Mayer,Germany,3,4444
That should have been made like this:
1,22,Hans Olsen,Denmark,333,4
1111,2,"Turner, Alfred",England,3333,4
1,222,Horst Mayer,Germany,3,4444
If you are positive that you know that the only field with embedded commas is the third then you can use a data step to read it in and generate a valid file.
data _null_;
infile bad dsd truncover ;
file good dsd ;
length v1-v6 dummy $200;
input v1-v2 #;
do i=1 to countw(_infile_,',','q')-5;
input dummy #;
v3=catx(', ',v3,dummy);
end;
input v4-v6 ;
put v1-v6 ;
run;
Once you have a properly formatted CSV file then it is easy to read.
data want;
infile good dsd truncover ;
length v1-v2 8 v3-v4 $40 v5-v6 8;
input v1-v6 ;
run;
But if the extra comma could be in any field then you will probably need to have a human fix those lines.
If your field value contains the field delimiter you will want to double quote the field value. Proc EXPORT will do such double quoting when the data base type is specified as CSV
Example:
data have;
A = 1;
B = 2;
C = 3;
D = 'x,y';
run;
filename csv temp;
proc export data=have outfile=csv dbms=csv;
run;
data _null_;
infile csv;
input;
put _infile_;
run;
The log will show the exported file contains double quoted values as needed in the csv file produced.
Log
A,B,C,D
1,2,3,"x,y"
I know for the infile statement, you can add a missover and truncover statement for missing values in the input, but if I'm using datalines for data instead of infile, is there an equivalent statement I can use?
You can still use infile by following it with datalines and then missover or truncover etc.
data _null_;
infile datalines missover;
input a b c;
put _all_;
datalines;
1 2
3 4
;
run;
%let dirname = C:\Users\data;
filename DIRLIST pipe 'dir/B &dirname\*.dbf';
/* Create a data set with one observation for each file name */
data dirlist;
length fname $8.;
infile dirlist length=reclen;
input fname $8.;
run;
data all_text (drop=fname);
set dirlist;
filepath = "&dirname\"||fname||".dbf";
infile dummy filevar = filepath length=reclen end=done missover;
do while(not done);
INPUT
F1 : 2.
F2 : 2.
F3 : 2.
F4 : 10.
F5 : 4.;
output;
end;
run;
The problem is that it is only reading the first line of each files and not the whole file before moving to the next. Also variable F1 are shown as missing.
Suggestions are welcome
So a standard proc import would be:
proc import out=sample1 datafile="path to dbf file.dbf" dbms=DBF replace;
run;
The problem now, is how to generate this set of code for every file in your file list. Using the CALL EXECUTE statement from #Tom is your best bet. You call also create a small macro and call it for each filename, using CALL EXECUTE. If you're new to SAS this can be easier to understand.
*Create a macro that imports the DBF
%macro import_dbf(input= , output=);
proc import out=&out datafile="&output" dbms=DBF replace;
run;
%mend;
Then call macro from dataset. I'm naming the datasets DBF001, DBF0002 etc.
%let dirname=C:\_localdata;
data dirlist;
informat fname $20.;
input fname;
cards;
data1.dbf
data2.dbf
data3.dbf
data4.dbf
;
run;
data out;
set dirlist;
str=catt('%import_dbf(input="', "&dirname", '\', fname, '", output=dbf',
put(_n_, z4.), ');');
run;
proc print data=out;
run;
Import them one by one and then combine them.
%let dirname = C:\Users\data;
data filelist ;
infile "dir /b &dirname\*.dbf" pipe truncover end=eof;
fileno + 1;
input fname $256. ;
tempname = 'temp'||put(fileno,z4.);
call execute(catx(' ','proc import replace dbms=dbf'
,'out=',tempname,'datafile=',quote(trim(fname)),';run;'
));
if eof then call symputx('lastname',tempname);
run;
data want ;
set temp0001-&lastname;
run;
Here is a simple code to read two files
filename one "C:\Users\Owner\Desktop\SAS\nbExce\ch1\1-12 one.txt" ;
filename two "C:\Users\Owner\Desktop\SAS\nbExce\ch1\1-12 two.txt" ;
data test ;
input extfile $ ;
infile dummy filevar=extfile end=last ;
do until (last) ;
input name $ score ;
output ;
end ;
datalines ;
one
two
;
run ;
proc print ;
run ;
Why do I get this error ? How can I improve my file references ?
You cannot refer to file assigned using a filename statement in the filevar. Use the full path to the files.
data test;
infile datalines dsd;
length extfile $128;
input extfile $;
infile dummy filevar=extfile end=last;
do until (last);
input name $ score;
output;
end;
datalines;
"C:\Users\Owner\Desktop\SAS\nbExce\ch1\1-12 one.txt"
"C:\Users\Owner\Desktop\SAS\nbExce\ch1\1-12 two.txt"
;
run;
Simple question.
PROC IMPORT OUT= braw.address
DATAFILE= "&path.\address_data.csv"
DBMS=csv REPLACE;
GETNAMES=YES;
RUN;
This statement will create the dataset columns as character or numeric depending on the values, which is smart, but not what I want.
I want to import them all as character, to make for easier regex evaluation.
Is there a simple way to do this?
I would generally just write my own input statement for the CSV, then you can make them whatever you want.
IE:
data braw.address;
infile "&path.\address_data.csv" dlm=',' dsd missover;
input
field1 $
field2 $
....
;
run;
You can use the log from the PROC IMPORT to generate this the first time and just edit it to contain $ for each variable.
If you do not want to write a SAS macro to read all the columns as character, you could try a "cheat". Manually edit the file and duplicate the first row (the one containing column headers. Since those will most likely all be character strings, SAS should import all the columns as character.
Of course, a macro to do this would not be that difficult. You can try something like this:
%macro readme(dsn,fn);
/* Macro to read all columns of a CSV as character */
/* Parameters: */
/* DSN - The name of the SAS data set to create */
/* FN - The external file to read (quoted) */
/* Example: */
/* %readme(want, 'c:\temp\tempfile.csv'); */
data _null_;
infile &fn;
input;
i = 1;
length headers inputstr $200;
headers = compress(_infile_,"'");
newvar = scan(headers,1,',');
do until (newvar = ' ');
inputstr = trim(inputstr) || ' ' || trim(newvar) || ' $';
i + 1;
newvar = scan(headers,i,',');
end;
call symput('inputstr',inputstr);
stop;
run;
data &dsn;
infile &fn firstobs=2 dsd dlm=',' truncover;
input &inputstr.;
run;
%mend;
%readme(want, 'c:\temp\tempfile.csv');
Here is my macro to read dlm file with all vars as char:
%MACRO ImportText(file,dsn,dlm);
* Read data use proc import to get variable name and length;
PROC IMPORT DATAFILE="&file" OUT=temp DBMS=dlm REPLACE;
DELIMITER = &dlm;
GETNAMES = YES;
GUESSINGROWS = 32767;
RUN;
* Put variable names into macro variable;
PROC CONTENTS DATA=temp out=vars NOPRINT; RUN;
PROC SQL NOPRINT;
SELECT CATT(name,' : $',length,'.') INTO :vars SEPARATED BY ' ' FROM vars ORDER BY varnum;
QUIT;
* Read real data;
DATA &dsn;
INFILE "&file" DELIMITER=&dlm MISSOVER DSD FIRSTOBS=2 LRECL=32767;
INPUT &vars;
RUN;
%MEND;