SAS increment macro variable yyyymm by 1 month - sas

Basically i'm trying to get the below month4 but in a macro format.
Been a while since i've done macro functions so this is a bit tricky.
data test;
input month $8.;
datalines ;
202210
202211
202201
202210
;
run;
data test2;
set test;
format month2 date9. month3 date9.;
test = cats(month,"01");
month2 = input(cats(month, "01"), yymmdd8.);
month3 = intnx("month",input(cats(month, "01"), yymmdd8.),-1);
month4=trim(substr(put(month3,yymmddn8.),1,6));
run;

I suspect this is what you are looking for, but your request is not very clear.
%let month=202212;
%let month4=%sysfunc(intnx(month,%sysfunc(inputn(&month,yymmn6)),1),yymmn6);
It uses the INPUTN() function to convert your YYYYMM string by reading it with the YYMMN6. informat. It then uses the INTNX() function to move to the beginning of the next month and returns the result formatted with YYMMN format so you get back another YYYYMM string of digits.

Related

Convert mm/dd/yy to MonthName DayNumber, YearNumber in SAS

I want to be able to convert an entire column of dates this way. For example, 01/01/2017 to January 1, 2017. I realize there is a convoluted way of doing this but I am not entirely sure how i'd approach that logically. Also, does there happen to be a SAS format that does this? Thanks.
There does happen to be a format you can use. Here is a worked example using test data:
data test;
input datestring $;
datalines;
01/01/2017
;
run;
Using input converts the string value into a SAS date, and then the put function is used to create a character variable holding the representation you are looking for:
data test2;
set test;
date_as_date = input(datestring,ddmmyy10.);
date_formatted = put(date_as_date,worddate20.);
run;
The number 20 is used to describe a length that is long enough to hold the full value, using a lower number may result in truncation, e.g.
date_formatted = put(date_as_date,worddate3.);
put date_formatted=;
dateformatted=Jan
In some cases, the desired date format may NOT exist (in this case, it does 'worddate20.'), but as an example...
You could either write a function-style macro to convert a SAS date to "monname + day, year" format, e.g.
%MACRO FULLMDY(DT) ;
catx(', ',catx(' ',put(&DT,monname.),put(&DT,day.)),put(&DT,year4.))
%MEND ;
data example1 ;
dt = '26jul2017'd ;
fulldate = %FULLMDY(dt) ;
run ;
Or, you could build a custom format, covering all the dates which may exist in your data, e.g.
data alldates ;
retain fmtname 'FULLMDY' type 'N' ;
do dt = '01jan1900'd to '01jan2100'd ;
mdy = catx(', ',catx(' ',put(dt,monname.),put(dt,day.)),put(dt,year4.)) ;
output ;
end ;
rename dt = start
mdy = label ;
run ;
proc format cntlin=alldates ; run ;
data example2 ;
dt = '26jul2017'd ;
format dt fullmdy. ;
run ;

Using intnx to get the same date last year in SAS

I want to pull the same date one year before my variable 'day_3_ago'
My code:
%macro date;
data _null_;
call symput ('day_3_ago', put(intnx('day',today(),-3, 'b'),yymmddn8.));
run;
%mend;
%date;
%let last_year_3dayago = [1 year before day_3_ago]
For example, if I ran this code today, day_3_ago would be 20170624. I would want last_year_3dayago to be 20160624
My current solution is:
%let last_year_3daygo = %sysfunc(intnx(day,%sysfunc(inputn(&day_3)ago.,yymmdd8)),-365),yymmddn8);
but that doesn't account for leap years.
Instead of using intnx with day, use year and end the function with s (or same) instead of b.
data _null_;
x = intnx('year',today()-3,-1,'s');
putlog x :date9.;
run;
I modified Longfish's code to solve your requirement with the variable last_year_3dayago:
%let last_year_3dayago = 20170624;
data _null_;
x = intnx('year',input("&last_year_3dayago.",b8601da.),-1,'s');
putlog x :date9.;
run;

SAS programming : Convert Exponential value to numeric value in SAS

How to convert exponential(for eg. 3.22254e2, 3.24456545e-3) values to numeric format(322.254,0.00324456545) in SAS. I am getting the source as varchar from a file and need to store the same in oracle as number format.
I need to read from a file(csv) so When i tried to do the same i get the result(b) as null.
My code:
data work.exp_num ;
infile 'exp_number.csv'
lrecl = 256
delimiter = '~'
dsd
missover
firstobs = 2;
;
attrib a length = $300
format = $32.
informat = $32.;
input a ;
run;
data test;
set work.exp_num;
b=input(a,32.16);
run;
Kindly help.
Thanks in advance.
You can use the standard informat w.d .
Here you got an example:
data test;
a='3.24456545e-3'; output;
a='3.22254e2'; output;
run;
data erg;
set test;
b=input(a,32.16);
run;

Populate SAS variable based on content of another variable

I have a variable, textvar, that looks like this:
type=1&name=bob
type=2&name=sue
I want to create a new table that looks like this:
type name
1 bob
2 sue
My approach is to use scan to split the variables on & so for the first observation I have
var1 var2
type=1 name=bob
So now I can use scan again to split on =:
vname = scan(var1, 1, '=');
value = scan(var1, 2, '=');
But how can I now assign value to the variable named vname?
PROC TRANPSOSE is the quickest way. You need an ID variable (dummy or real).
data test;
informat testvar $50.;
input testvar $;
datalines;
type=1&name=bob
type=2&name=sue
;;;;
run;
data test_vert;
set test;
id+1;
length scanner $20 vname vvalue $20;
scanner=scan(testvar,1,"&");
do _t=2 by 1 until (scanner=' ');
vname=scan(scanner,1,"=");
vvalue=scan(scanner,2,"=");
output;
scanner=scan(testvar,_t,"&");
end;
run;
proc transpose data=test_vert out=test_T;
by id;
id vname;
var vvalue;
run;
Does this help? Dynamic variable names in SAS
I think I have some code to address this, but left it at my workplace.
Obviously you haven't included your real data, but can't you just hard code some of the values if the format of the raw data is the same in each row? My code converts the "=" and "&" to "," to make the scan function easier to use.
data want (keep=type name);
set test;
_newvar=translate(testvar,",,","&=");
type=input(scan(_newvar,2),best12.);
length name $20;
name=scan(_newvar,4);
run;

How can I make a character variable equal to the formatted value of a numeric variable for arbitrary SAS formats?

If I have a numeric variable with a format, is there a way to get the formatted value as a character variable?
e.g. I would like to write something like the following to print 10/06/2009 to the screen but there is no putformatted() function.
data test;
format i ddmmyy10.;
i = "10JUN2009"d;
run;
data _null_;
set test;
i_formatted = putformatted(i); /* How should I write this? */
put i_formatted;
run;
(Obviously I can write put(i, ddmmyy10.), but my code needs to work for whatever format i happens to have.)
The VVALUE function formats the variable passed to it using the format associated with the variable. Here's the code using VVALUE:
data test;
format i ddmmyy10.;
i = "10JUN2009"d;
run;
data _null_;
set test;
i_formatted = vvalue(i);
put i_formatted;
run;
While cmjohns solution is slightly faster than this code, this code is simpler because there are no macros involved.
Use vformat() function.
/* test data */
data test;
i = "10jun2009"d;
format i ddmmyy10.;
run;
/* print out the value using the associated format */
data _null_;
set test;
i_formatted = putn(i, vformat(i));
put i_formatted=;
run;
/* on log
i_formatted=10/06/2099
*/
This seemed to work for a couple that I tried. I used VARFMT and a macro function to retrieve the format of the given variable.
data test;
format i ddmmyy10. b comma12.;
i = "10JUN2009"d;
b = 123405321;
run;
%macro varlabel(variable) ;
%let dsid=%sysfunc(open(&SYSLAST.)) ;
%let varnum=%sysfunc(varnum(&dsid,&variable)) ;
%let fmt=%sysfunc(varfmt(&dsid,&varnum));
%let dsid=%sysfunc(close(&dsid)) ;
&fmt
%mend varlabel;
data test2;
set test;
i_formatted = put(i, %varlabel(i) );
b_formatted = put(b, %varlabel(b) );
put i_formatted=;
put b_formatted=;
run;
This gave me:
i_formatted=10/06/2009
b_formatted=123,405,321
I can do this with macro code and sashelp.vcolumn but it's a bit fiddly.
proc sql noprint;
select trim(left(format)) into :format
from sashelp.vcolumn
where libname eq 'WORK' and memname eq 'TEST';
run;
data test2;
set test;
i_formatted = put(i, &format);
put i_formatted;
run;
Yes, there is a putformatted() function. In fact, there are two: putc() and putn(). Putc handles character formats, putn() numeric. Your code will need to look at the format name (all and only character formats start with "$") do determine which to use. Here is the syntax of putc (from the interactive help):
PUTC(source, format.<,w>)
Arguments
source
is the SAS expression to which you want to apply the format.
format.
is an expression that contains the character format you want to apply to source.
w
specifies a width to apply to the format.
Interaction: If you specify a width here, it overrides any width specification
in the format.