Within a data setp I am using a "call execute" like the one below:
Everything works fine except the last 2 variables mhstdtc2 and mhendtc2, these variables are num type with an informat and format of date9.
I receive a note that numeric variables are being converted to character on that line, How should the dates be inserted on the call execute statment. Thanks
I have tried removing the quotes which creates a messy call execute
call execute("proc sql;
insert into leaddata values("||subjid||","||mhterm||","||mhstdtc_dtr||","||mhstdtc_dtr||","||mhstdtc_dtr||","||sitemnemonic||","||mhstdtc2||"d,"||mhendtc2||"d);quit;");
Before generating code make sure you know what code you want to generate. Looks like you are trying to generate something like this:
values(101,Stomach Pain,30NOV2018,15DEC2018,Clinic 47);
But you need to generate quotes around your character variables. Also there is no need to convert your dates into human readable date literals, just leave them as the raw number of days.
call execute(catx(' ','proc sql;','insert into leaddata','values('
,catx(',',quote(subjid),quote(mhterm),date1,number2,....)
,');quit;'));
But if you have the data in a dataset why not just insert directly from the data set?
insert into leaddata select subjid,mhterm,.... from have ;
Related
I'm trying to convert a SAS dataset column to a list of macro variables but am unsure of how indexing works in this language.
DATA _Null_;
do I = 1 to &num_or;
set CondensedOverrides4 nobs = num_or;
call symputx("Item" !! left(put(I,8.))
,"Rule", "G");
end;
run;
Right now this code creates a list of macro variables Item1,Item2,..ItemN etc. and assigns the entire column called "Rule" to each new variable. My goal is to put the first observation of "Rule" in Item1, the second observation in that column in Item2, etc.
I'm pretty new to SAS and understand you can't brute force logic in the same way as other languages but if there's a way to do this I would appreciate the guidance.
Much easier to create a series of macro variables using PROC SQL's INTO clause. You can save the number of items into a macro variable.
proc sql noprint;
select rule into :Item1-
from CondensedOverrides4
;
%let num_or=&sqlobs;
quit;
If you want to use a data step there is no need for a DO loop. The data step iterates over the inputs automatically. Put the code to save the number of observations into a macro variable BEFORE the set statement in case the input dataset is empty.
data _null_;
if eof then call symputx('num_or',_n_-1);
set CondensedOverrides4 end=eof ;
call symputx(cats('Item',_n_),rule,'g');
run;
SAS does not need loops to access each row, it does it automatically. So your code is really close. Instead of I, use the automatic variable _n_ which can function as a row counter though it's actually a step counter.
DATA _Null_;
set CondensedOverrides4;
call symputx("Item" || put(_n_,8. -l) , Rule, "G");
run;
To be honest though, if you're new to SAS using macro variables to start isn't recommended, there are usually multiple ways to avoid it anyways and I only use it if there's no other choice. It's incredibly powerful, but easy to get wrong and harder to debug.
EDIT: I modified the code to remove the LEFT() function since you can use the -l option on the PUT statement to left align the results directly.
EDIT2: Removing the quotes around RULE since I suspect it's a variable you want to store the value of, not the text string 'RULE'. If you want the macro variables to resolve to a string you would add back the quotes but that seems incorrect based on your question.
Using hptmine procedure in SAS, is it possible to write the output to the same file or write to a file in the same format as in the input after Stemming operation is done
It seems it is not possible. Stemming is the part of parsing phase of hptmine procedure. According to documentation the only output data set for parse statement that contains a full list of terms after stemming operation is done, is OUTTERMS= data set.
Instead, to replace terms for their stems in your original file, you can make use of OUTTERMS= data set in a sas code that will follow hptmine procedure.
For example, create a dictionary:
proc sql;
create table work.child_parent as
select child.term as term_child, parent.term as term_parent
from OUTTERMS child
inner join OUTTERMS parent
on child.parent = parent.key
where child._ispar="." and child.role ne "NOUN_GROUP"
;
quit;
and use the dictionary as a lookup table in a code that goes through original text file and replaces each encountered term_child for its stem -term_parent.
I have a dataset(liste_institution) that contain all the name of the variable that I want to "define" in my proc report statement. Here is my code that work when I call my macro not dynamically(%create_institution(815);). If I use the data statement with the call execute(in comment in my code) it not working. The reason seem to be that when I use the call execute the code is not interpreted in a PROC REPORT that is why it give me error.
proc report data = ventes_all_inst4
missing split = "*" nowd
style(header)=[font_weight=bold background = #339966 foreground = white]
style(column)=[cellwidth=15cm];
%macro create_institution(institution);
define TOTAL_&institution. / display "TOTAL*($)" style(column)=[cellwidth=4cm];
%mend;
/* Give error when I use this data step */
/*data _null_;
set liste_institution;
call execute('%create_institution(' || INS || ');');
run;*/
%create_institution(815);
run;
Is there an easy way to create dynamically define statement in a PROC REPORT from a dataset that contain the column name.
Basically, you have a misunderstanding of how macros work and timing. You need to compile the macro list previous to the proc report, but you can't use call execute because that actually executes code. You need to create a macro variable.
Easiest way to do it is like so:
proc sql;
select cats('%create_institution(',ins,')')
into :inslist separated by ' '
from liste_institution
;
quit;
which makes &inslist which is now the list of institutions (with the macro call).
You also may be able to use across variables to allow this to be easier; what you'd have is one row per ins, with a single variable with that value (which defines the column name) and another single variable with the value that goes in the data table portion. Then SAS will automatically create columns for each across value. Across variables are one of the things that makes proc report extremely powerful.
I have a SAS procedures that runs every morning and it takes in a raw data file for the day called "Filename_20141117.txt". The last part of the file name is changing everyday to the date for that day.
I want to make the INFILE statement in my SAS script smarter so that it knows to get the current day's file. I was trying to do a date concatenation, something like this:
infile cat('G:\Finance\RawData\Filename_',year(today()),month(today()),day(today()),'.txt')
Also, is there a way to declare variables and work with them in SAS, and not have them created as a table in your output? I'm a C/C#/VB programmer learning to program in SAS.
I was thinking that i could make 3 string variables - day, month, and year. Populate each variable with the corresponding value using the Day(), Month() and Year() function, with Today() as the date input. Then i was going to take these 3 variables and concatenate them to get my '20141118' that would be located at the end of the .txt file.
However it doesn't like me doing this. If anyone knows how to do this that would be fantastic. I'm very new to SAS Programming and its concepts.
Thanks in advance.
The most basic version of your statement would be:
INFILE "G:\Finance\RawData\Filename_%sysfunc(today(),yymmddn8.).txt";
To explain fully:
%sysfunc is a macro function in SAS which allows you to use data-step functions in open code, it takes one (optionally two) arguments:
The first argument of %sysfunc is the data-step function in question, in this case we want the value of TODAY(), so that is used.
The second argument (optional) provides the SAS format in which the result should be returned. The SAS format of choice for the date representation you need is yymmddn8. (literally year_year_month_month_day_day, the n represents 'no-separators', and 8 is the length). (e.g. 20141118)
If we were to omit the second argument, we'd get the number of days since 01JAN1960.
If I were to run the statement today it would look like this:
INFILE "G:\Finance\RawData\Filename_20141118.txt";
Also, use of double-quotes here is required because we are using a macro function. If we used single quotes, it would look for a file with the unresolved value of the string above and would most likely fail.
To check what it would resolve to, simply add %PUT to the front of the line, and then just run that line in isolation. The log will show what is returned.
I need to change the variable length in a existing dataset. I can change the format and informat but not the length. I get an error. The documentation says this is possible but there are no examples.
Here is my issue. My data source could change so I don't want to pre define columns on import. I want to do a generic import and then look for certain columns and adjust the length.
I have tried PROC SQL and DATA steps. It looks like the only way to do this is to recreate the dataset or the column. Which I don't want to do.
Thanks,
Donnie
If you put your LENGTH statement before the SET statement, in a Data step, you can change the length of a variable. Obviously, you will get truncation if you have data longer than your new length.
However, using a DATA step to change the length is also re-creating the data set, so I'm confused by that part of your question.
The only way to change the length of a variable in a datastep is to define it before a source (SET) dataset is read in.
Conversely you can use an alter statement in a proc sql. SAS support alter statement
Length of a variable remains same once you set the dataset. Add length statements before you set the dataset if you need to change length of a columns
data a;
length a, b, c $200 ;
set b ;
run ;