Proc format variable format not showing up - sas

I am trying to apply format to a variable in a data set, but after running the data step, I am still only seeing the raw values ( eg -1) instead of formatted values( eg -1=INAPPLICABLE). minimal re-producible code example below. Any help at all greatly appreciated.
proc format library=PUFLIB;
'-1' = '-1 INAPPLICABLE'
'1' = '1 YES'
'2' = '2 NO'
'3' = '3 DOES NOT WORK'
;
run;
data example_ds;
FORMAT ACCDNWRK $ACCDNWRK_FMT.;
input accdnwrk $;
datalines;
1
2
3
-1
;

Please ensure to review your log.
It shows that the error is right after your PROC FORMAT statement. In this case you're missing the code that tells you SAS if the format is a informat or format and the format name.
70
71 proc format library=PUFLIB;
72 '-1' = '-1 INAPPLICABLE'
____
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
73 '1' = '1 YES'
74 '2' = '2 NO'
75 '3' = '3 DOES NOT WORK'
76 ;
NOTE: The previous statement has been deleted.
77 run;
NOTE: PROCEDURE FORMAT used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
Adding in value to indicate it's a format and then the format name, accwrk_fmt is what's needed.
proc format library=puflib;
value accwrk_fmt
*rest of your code*

You seem to want a numeric format. Hope this helps you
proc format;
value ACCDNWRK_FMT
-1 = '-1 INAPPLICABLE'
1 = '1 YES'
2 = '2 NO'
3 = '3 DOES NOT WORK'
;
run;
data example_ds;
FORMAT ACCDNWRK ACCDNWRK_FMT.;
input accdnwrk;
datalines;
1
2
3
-1
;

Related

Literal contains unmatched quote

I have a numeric parameter given to my macro and would like to convert it to date, set to end of month and apply a format.
Following code works for many dates, but not for march; throws 'Literal contains unmatched quote'.
proc format;
picture mydatep
low-high = "'%0d-%0b-%0Y'" (datatype = date);
%macro test(cycle=);
%let enddate = %SYSFUNC(intnx(month, %SYSFUNC(inputn(&cycle., yymmn6.)), 0, e), mydatep.);
%put &enddate.;
%mend;
%test(cycle=201602); /* works --> 29-Feb-2016*/
%test(cycle=201603); /* works not */
%test(cycle=201604); /* works again --> 30-Apr-2016*/
%test(cycle=201402); /* works --> 28-Feb-2014*/
%test(cycle=201403); /* works not */
%test(cycle=201404); /* works again --> 30-Apr-2014*/
I have been using the code for some years now, and never had trouble with it. I am using SAS Analytics Pro 9.4
Solution: I was starting the SAS session via SAS (Unicode). Switching to SAS (Deutsch) [engl: SAS (German)], solved the issue.
I don't know why, though.
#Kenji: "Switching to SAS (Deutsch) [engl: SAS (German)], solved the issue. I don't know why, though."
The explanation is quite simple, some date formats in German and English differ in just a few cases:
German English equal?
----------------------------------------
01Jan2022 01Jan2022 yes
01Feb2022 01Feb2022 yes
01Mär2022 01Mar2022 NO
01Apr2022 01Apr2022 yes
...
01Okt2022 01Oct2022 NO
01Nov2022 01Nov2022 yes
01Dez2022 01Dec2022 NO
So in a German environment, it is a common observation that your code might work in most cases but not for March, October and December.
If you used an endash or emdash instead of hyphens in your PICTURE text that would change the generated character string from 12 bytes to 13 or 14 bytes. Those non ASCII characters require more than one byte of storage.
So if your code used a width of 12 with that format then the value would be truncated removing the closing quote and possibly the last digit of the year also.
Tell PROC FORMAT that the default width for the format should be 14 and not 13.
proc format;
picture mydatep (default=14)
low-high = "'%0d-%0b-%0Y'" (datatype = date);
run;
Example:
23 proc options option=ENCODING option=LOCALE option=DATESTYLE option=DFLANG ;
24 run;
SAS (r) Proprietary Software Release 9.4 TS1M5
ENCODING=UTF-8 Specifies the default character-set encoding for the SAS session.
LOCALE=EN_US Specifies a set of attributes in a SAS session that reflect the language, local conventions, and culture for a
geographical region.
DATESTYLE=MDY Specifies the sequence of month, day, and year when ANYDTDTE, ANYDTDTM, or ANYDTTME informat data is ambiguous.
DFLANG=GERMAN Specifies the language for international date informats and formats.
NOTE: PROCEDURE OPTIONS used (Total process time):
real time 0.03 seconds
cpu time 0.01 seconds
25
26 options dflang=german locale=de_DE ;
27
28 data test;
29 do month=1 to 12;
30 length string $20 ;
31 string=put(mdy(month,1,2000),mydatep.);
32 put month= string=;
33 end;
34 run;
month=1 string='01-Jan-2000'
month=2 string='01-Feb-2000'
month=3 string='01-Mär-2000
month=4 string='01-Apr-2000'
month=5 string='01-Mai-2000'
month=6 string='01-Jun-2000'
month=7 string='01-Jul-2000'
month=8 string='01-Aug-2000'
month=9 string='01-Sep-2000'
month=10 string='01-Okt-2000'
month=11 string='01-Nov-2000'
month=12 string='01-Dez-2000'
NOTE: The data set WORK.TEST has 1 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
35 proc format;
36 picture mydatep (default=14)
37 low-high = "'%0d-%0b-%0Y'" (datatype = date);
NOTE: Format MYDATEP is already on the library WORK.FORMATS.
NOTE: Format MYDATEP has been output.
38 run;
NOTE: PROZEDUR FORMAT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
39
40 data test;
41 do month=1 to 12;
42 length string $20 ;
43 string=put(mdy(month,1,2000),mydatep.);
44 put month= string=;
45 end;
46 run;
month=1 string='01-Jan-2000'
month=2 string='01-Feb-2000'
month=3 string='01-Mär-2000'
month=4 string='01-Apr-2000'
month=5 string='01-Mai-2000'
month=6 string='01-Jun-2000'
month=7 string='01-Jul-2000'
month=8 string='01-Aug-2000'
month=9 string='01-Sep-2000'
month=10 string='01-Okt-2000'
month=11 string='01-Nov-2000'
month=12 string='01-Dez-2000'
NOTE: The data set WORK.TEST has 1 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.00 seconds

Proc Tabulate: Reordering a Formatted Variable

I created a day variable using the following code:
DAY=datepart(checkin_date_time); /*example of checkin_date_time 1/1/2014 4:44:00*/
format DAY DOWNAME.;
Sample Data:
ID checkin_date_time Admit_Type BED_ORDERED_TO_DISPO
1 1/1/2014 4:40:00 ICU 456
2 1/1/2014 5:64:00 Psych 146
3 1/1/2014 14:48:00 Acute 57
4 1/1/2014 20:34:00 ICU 952
5 1/2/2014 10:00:00 Psych 234
6 1/2/2014 3:48:00 Psych 846
7 1/2/2014 10:14:00 ICU 90
8 1/2/2014 22:27:00 ICU 148
I want to analyze some data using Proc Tab where day is one of the class variables and have the day of week appear in chronological order in the output; however, the output table begins with Tuesday. I would like it to start with Sunday. I've read over the the following page http://support.sas.com/resources/papers/proceedings11/085-2011.pdf and tried the proc format invalue code but it's producing a table that where the "day of week" = "21". Not quite sure where to go from here.
Thanks!
proc format;
invalue day_name
'Sunday'=1
'Monday'=2
'Tuesday'=3
'Wednesday'=4
'Thursday'=5
'Friday'=6
'Saturday'=7;
value day_names
1='Sunday'
2='Monday'
3='Tuesday'
4='Wednesday'
5='Thursday'
6='Friday'
7='Saturday';
run;
data Combined_day;
set Combined;
day_of_week = input(day,day_name.);
run;
proc tabulate data = Combined_day;
class Day Admit_Type;
var BED_ORDERED_TO_DISPO ;
format day_of_week day_names.;
table Day*Admit_Type, BED_ORDERED_TO_DISPO * (N Median);
run;
Fundamentally, you are confusing actual values with displayed values (i.e., formats). Specifically, datepart extracts the date portion out of a date/time field. Then, applying a format only changes how it is displayed not actual underlying value. So below DAY never contains the character values of 'WEDNESDAY' or 'THURSDAY' but original integer value (19724 and 19725).
DAY = datepart(checkin_date_time); // DATE VALUE
format DAY DOWNAME.; // FORMATTED DATE VALUE (SAME UNDERLYING DATE VALUE)
Consider actually assigning a column as weekday value using WEEKDAY function. Then apply your user-defined format for proc tabulate.
data Combined_day;
set Combined;
checkin_date = datepart(checkin_date_time); // NEW DATE VALUE (NO TIME)
format checkin_date date9.;
checkin_weekday = weekday(checkin_date); // NEW INTEGER VALUE OF WEEKDAY
run;
proc tabulate data = Combined_day;
class checkin_weekday Admit_Type;
var BED_ORDERED_TO_DISPO ;
format checkin_weekday day_names.; // APPLY USER DEFINED FORMAT
table checkin_weekday*Admit_Type, BED_ORDERED_TO_DISPO * (N Median);
run;

change the order of bars on sas graph

I have a macro that produce a graph as in image graph. I want to change the order of bars to Dev 201601 201602 201603 201604 201605 instead of
201601 201602 201603 201604 201605 Dev. Here is my code
goptions reset=global gunit=pct border cback=white
colors=(black red green blue) ftitle=swissb
ftext=ZAPFB htitle=5 htext=1.7
offshadow=(1.5,1.5);
axis1 label=none;
axis2 label=none value=none
order=(0 to 110 by 10)
major=none
minor=none;
legend1 cborder=black cblock=CXF0E68C label=none
shape=bar(3,3)
POSITION=(bottom center);
pattern1 color=vpapb;
pattern2 color=bigy;
pattern3 color=paoy;
pattern4 color=vligb;
pattern5 color=lipk;
pattern6 color=vpap;
pattern7 color=pab;
pattern8 color=lio;
proc gchart data= Recent.char_&value;
title ;
vbar Period / sumvar=Percent
subgroup=&value
inside=subpct
width=12
space=8
maxis=axis1
raxis=axis2
legend=legend1
cframe=BWH
coutline=black;
What should I do to solve the problem?
The easiest way to do this is to have your bar value be an ordering value that you use a format to display as your actual value. So here I have 0 = Dev, 1 = 201601, 2 = 201602, etc.; I use a picture format to get there since things work so nicely, but you could use a regular value format if there's not a simple logical mapping like this.
data test_data;
input period value; /* you may need to convert from '201601' to '1' if your data already has 201601 type values; use an informat (opposite of format). */
datalines;
1 10
2 20
3 25
4 25
5 30
0 20
;;;;
run;
proc format;
picture periodF
0 = 'Dev' /* map 0 to Dev */
1-12 = 99 (prefix='2016'); /* for values 1-12, display in 2 digit zero padded format, prefix with 2016) */
quit;
proc sgplot data=test_data;
format period periodf.; /*apply format here or in an earlier datastep */
vbar period/response=value;
run;

SAS Put statement - Why it can be used to convert char to number?

The code is very simple:
data test (keep = state state_num);
set raw1314.accident2013_prf;
state_num= put(state,z2.);
run;
variable "state" contains state names and the output of this program is:
Obs STATE state _num
1 Alabama 01
But isn't "put" function is used to convert numerical values into character values? Why it maps "Alabama" to "01" here?
Thanks in advance.
Your variable STATE must be numeric (1) and have a format applied to it or character (01) with a format applied. If it was the character value of Alabama this would not occur.
data _null_;
x=put('Alabama', z2.);
put x;
run;
Results:
55
56 data _null_;
57 x=put('Alabama', z2.);
___
484
NOTE 484-185: Format $Z was not found or could not be loaded.
58 put x;
59 run;
Al

Proc informat using cntlin option

I am trying to make character informat from the range values given in a dataset.
Dataset : Grade
Start End Label Fmtname Type
0 20 A $grad I
21 40 B $grad I
41 60 C $grad I
61 80 D $grad I
81 100 E $grad I
And here is the code i wrote to create the informat
proc format cntlin = grade;
run;
And now the code to create a temp dataset using the new informat
data temp;
input grade : $grad. ## ;
datalines;
21 30 0 45 10
;
The output i wanted was a dataset Temp with values :
Grade
A
B
A
..
Whereas the dataset Temp has values :
Grade
21
30
0
...
SAS Log Entry :
1146 proc format cntlin = grade;
NOTE: Informat $GRAD has been output.
1147 run;
NOTE: PROCEDURE FORMAT used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
NOTE: There were 5 observations read from the data set WORK.GRADE.
1148
1149
1150 data temp;
1151 input grade : $grad. ## ;
1152
1153 datalines;
NOTE: SAS went to a new line when INPUT statement reached past the end of a
line.
NOTE: The data set WORK.TEMP has 5 observations and 1 variables.
NOTE: DATA statement used (Total process time):
real time 0.03 seconds
cpu time 0.03 seconds
I am not able to understand why informat is not working. Can anyone please
explain where i am making my mistake.
INFORMATS convert characters to (characters or numbers). So you can't use START/END the way you are doing so, since that only works with numbers.
See the following:
proc format;
invalue $grade
'0'-'20'="A"
'21'-'40'="B"
'41'-'60'="C"
'61'-'80'="D"
'81'-'100'="E";
quit;
proc format;
invalue $grade
'21'='A';
quit;
The latter works, the former gives you an error. So, you could write a dataset with all 101 values (each on a line with START), or just write a format and do it in a second step (read in as a number and then PUT to the format).