How to parse format from given data? - sas

I want to extend the question asked at Sum consecutive observations by some variable.
When I define the following macro variable
%let varnames=id dose supply date;
Since I don't know the fomat of the original data, how do I get the format for the rename automatically to apply it in the following extract of the above link?
data want(drop=id_i dose_i supply_i date_i);
format id dose supply 8. date mmddyy10.;
retain id dose supply date;
set have(rename=(id=id_i dose=dose_i supply=supply_i date=date_i)) end=last;

Related

SAS character and numeric change with set statement

I am working to merge two data sets and get the following error:
Variable DOB has been defined as both character and numeric.
Here is my code. I know I need a set statement to change the character to numeric. I was thinking:
DATA Merged1;
SET Aug21 Aug22;
RUN;
set (rename=(DOB=DOBnum));
length DOB $ 10.;
DOB= put(DOBnum,f10. -L);
drop DOBnum;
Would this be placed before my Set statement to merge to Aug 21 Aug 22?
Thank you!
I tried to run the code but it would not merge, unsure if where the Set statement for DOB would go
You do not need the second SET statement. You need to add the RENAME= dataset option to the dataset where it is mentioned in the first SET statement.
So something like:
DATA BOTH;
SET Aug21 Aug22(in=in2 rename=(DOB=DOBnum));
if in2 then DOB= put(DOBnum,f10. -L);
drop DOBnum;
RUN;
To get a more detailed answer provide more details about the variables and the types of values they contain. For example if DOB means Date of Birth then it does not make much sense to use the F format. If DOB should be an actual DATE then it should be numeric and not character. And if the version that is numeric has actual date values then converting them to text using the F format is going to generate strings that will be confusing for humans.
If you're a beginner I recommend two steps so you can trace the work.
Convert dob from character to numeric
Append the two datasets together (assume you're stacking the data sets)
Use format to control how the date is displayed
*convert character to numeric SAS date;
data aug21_convert2num;
set aug21(rename=dob=dobchar);
dob = input(dob, anydtdte.);
drop dobchar;
run;
*append the two data sets;
data want;
set aug21_convert2num aug22;
format dob yymmdd10.;
run;

How to select a single value from a table, to use for comparison(greater than/less than)?

I am handing over some code to a colleague, which is to be run daily to generate reports.
Once every month a new cycle starts, and we have to update the code for cycle_start_date
data mtd_table;
set ytd_table;
where entry_date> '10Mar2021'd; /*different every month*/
run;
Since he'll be running them from now on, along with other reports from other teams, I don't want to bother him every month to tweak the code. So I devised this:
i run(once a month)
data shared1.cycle_start_date;
cycle_start_date='10Mar2021'd;
run;
he runs(everyday)
data mtd_table;
set ytd_table;
where entry_date>/*(select cycle_start_date from shared1.cycle_start_date)*/;
run;
I'm not sure how to correctly implement this (select cycle_start_date from shared1.cycle_start_date) part, since it is from proc sql. Would appreciate help.
When you store program parameters in a data set (called control data) one use case is having later code extract the values into macro variables, at which point other code can resolve the macro variable for replacement at (automatic) step compile and run time. Two ways to extract values into macro variables are:
Proc SQL, SELECT ... INTO :<macro-variable>, and
DATA _NULL_, CALL SYMPUT(<macro-variable>, <data step expression>);
Don't forget, macro resolution replaces the macro variable as source code text. Dates in macro variables can be either the SAS data value (the text representation of a SAS date integer) or part of a date literal (the text <dd-mon-yyyy>) that would be resolved as source date literal "&<macro-variable>"D when to be utilized as a date value. The date literal part is used when you want to show the date value as human readable in when output; for example: TITLE "cycle start: &cycle_start_date";
Control data (you)
Rebuild or edit values in data set (name it parameters to be more useful)
data shared1.parameters;
cycle_start_date = '10Mar2021'd; * stored as a SAS date value (integer);
run;
Note: Some control data layouts use a name/value organization and has one row per parameter.
Other
Extract date value as SAS date value text, and as date literal text portion and use.
proc sql noprint;
select
cycle_start_date
, cycle_start_date format=date11.
into
:cycle_start_date_value trimmed
, :cycle_start_date_literal trimmed
from
shared1.parameters
;
%put &=cycle_start_date_value;
%put &=cycle_start_date_literal;
/*
* will log the macro variable value as follows:
* CYCLE_START_DATE_VALUE=22349 and
* CYCLE_START_DATE_LITERAL=10-MAR2021
*/
data ...
set ...;
where date >= &cycle_start_date; *resolve parameter as text representation of a SAS date value (integer);
...
title "Cycle starts: &cycle_start_date_literal";
proc print data=...; * title in output shows human readable part of date;
run;
Another approach is to use a common source code file that is %included by others. You would edit or recreate the parameters file by whatever process you want.
parameters.sas
%let cycle_start_date = 10-Mar-2021;
use
%include 'parameters.sas';
data ...
set ...;
where date >= "&cycle_start_date"D; *resolve parameter as part of date literal;
...
title "Cycle starts: &cycle_start_date";
proc print data=...; * title in output shows human readable part of date literal;
run;
One possible solution would be to put the date from the cycle_start_date table that is in the shared library shared1 into a macro-variable date that will be used in your data step to filter the ytd_table table based on the entry_date variable.
proc sql noprint;
select cycle_start_date into :date
from shared1.cycle_start_date;
quit;
data mtd_table;
set ytd_table;
where entry_date > &date.;
run;

SAS proc format dynamic values

PROC FORMAT;
VALUE $Gender 'M'='Male'
'F'='Female';
In the above I am passing the value for processing format as 'm'= 'male'
And 'f'='female' ... The same way I need that values to be passed from a file and the values of process format comes dynamically. How do I do that.
Like I need to pass the above mapping m=male, f=female from a file and read the file and pass that mapping to proceed format dynamically.
To do what you are asking, is done if you can place your data into Data set, two steps process
1- Get your raw data into data set
2- Use above data set to get desired format
so let do this-
*step 1-;
DATA fmt;
Infile "Textfile.txt" DSD ;
Retain fmtname '$myfmt'; /*myfmt is what your format name*/;
Length start $2 label $50;
Input start label ;
RUN;
Now since above code will create a dataset with Male female information use same dataset to create your format.
*Step2:
PROC FORMAT CNTLIN=fmt;
RUN;
The simplest way to create a format from a data set is to use the CNTLIN= option in PROC FORMAT.
REQUIRED VARIABLES IN THE FORMAT DATASET (FMTNAME, START, AND LABEL)
Variable Used for
FMTNAME- The format name
START - The left side of the formatting = sign (assumed character) –
must be unique unless defining a Multi-Label format
LABEL- The right side of the formatting = sign

Convert number to date format in SAS

What I have
I have a column/variable named Release_Date with length 8 format 11. and informat 11.
The observation in that column are in the form YYYYMMDD SAS actually reads them as pure number
What I want
I want to convert those observation in DD/MM/YYYY format with format and informat as DDMMYY10.
Example
Release_Date is 20180612 then I want 12/06/2018
Any help with this regard will be appreciated
Convert to character
Read back in as date
make sure the variable is different since SAS does not allow you to change a variable type
releaseDate_NUM = input(put(Release_Date, 8. -l), yymmdd10.);
The following solution creates a simple dataset, then processes that dataset to add the converted date:
data myDates;
input intDate;
datalines;
20110101
20120202
;run;
data myDates;
set myDates;
format cvtDate mmddyy10.; * create new variable by specifying the format;
cvtDate = input(put(intDate,8.),yymmdd8.); * assign new variable value;
run;
Results should be:
intDate cvtDate
-------- ----------
20110101 01/01/2011
20120202 02/02/2012

Using informats when creating a dataset from another dataset

I've got a dataset that's full of data all in character format.
Now I want to create another dataset from this one, put put everything it it's correct decimal or date or character format.
Here's what I'm trying.
data work.testout;
attrib account_open_date informat = mmddyy10.;
do i = 1 to nobs;
set braw.accounts point = i nobs = nobs;
output;
end;
stop;
run;
this gives me:
Variable 'account_open_date' from data set braw.accounts (at line 7 column 21) has a different type (character) to the variable type on the data vector (numeric)
What's the best way of doing this?
You cannot use an informat to convert a variable directly from character to numeric. At least in SAS proper, you cannot convert a variable from character to numeric, period, without using an intermediary. You must do something along the lines of the following:
data want;
set have(rename=varwant=temp);
varwant=input(temp,MMDDYY10.);
drop temp;
run;
There you rename the (character) variable to a temporary name, then convert it to numeric using INPUT.