BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Whitlea
Obsidian | Level 7

I would like to reorder my month variable so that instead of months 1-12 least to greatest, I would like it in the order from June -July (07,08,09,10,11,12,01,02,03,04,05,06). I tried using proc format to reorder the variable, but it did not order the months correctly when I applied that format in a proc tabulate.   The month variable is a character variable ($2).  Thanks for the help!

proc format;
value $months
1='07'
2='08'
3='09'
4='10'
5='11'
6='12'
7='01'
8='02'
9='03'
10'04'
11='05'
12='06';
run;

Proc tabulate data =work.pt format=dollar12.;
class  Month;
format Month $months.;
var pay ;
table pay=' '* Month=' ' ;
run;

 

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

First make sure your format definition is correct. You are missing an = for the 10. Really a good idea to use quotes on both sides for a character format just to avoid confusion.

 

Try:

proc sort data=pt sortseq=linguistic(numeric_collation=on);
   by month;
run;
Proc tabulate data =work.pt format=dollar12.;
class  Month/order=data;
format Month $months.;
var pay ;
table pay=' '* Month=' ' ;
run;

The options on Proc sort should sort the month by numeric value not character order.

Then the option Order=data on the class says use the values as they appear in the data set.

 

Or perhaps: Formats are typically stored in a sort order (which is different than the result you want). The NOTSORTED makes them appear in order in the stored format as assigned. Then the interaction of order=data and Preloadfmt places the result in stored order. Note that preloadfmt will also produce values in the report that may not have occurred in the data if you use the Printmiss option.

proc format out=fmt;
value $months (notsorted)
1='07'
2='08'
3='09'
4='10'
5='11'
6='12'
7='01'
8='02'
9='03'
10='04'
11='05'
12='06';
run;

Proc tabulate data =work.pt format=dollar12.;
class  Month/order=data preloadfmt;
format Month $months.;
var pay ;
table pay=' '* Month=' '/printmiss ;
run;

View solution in original post

6 REPLIES 6
mkeintz
PROC Star

By using a leading $, you have correctly recognized that you need to create a character variable format.  But you provided a list of numeric values to be formatted.  You need to provide a list of character values to be formatted, as below:

 

data have;
 input month $2.    sales  @@;
datalines;
01 101   02 102   03 103   04 104   05 105   06 106
07 107   08 108   09 109   10 110   11 111   12 111
run;
proc format;
  Value $fiscal_mnth   /*Fiscal year from July through June */
'01'='07'   '02'='08'   '03'='09'   '04'='10'   '05'='11'   '06'='12'
'07'='01'   '08'='02'   '09'='03'   '10'='04'   '11'='05'   '12'='06'
;
run;
proc tabulate data=have  order=formated;
  class month;
  format month $fiscal_mnth2.;
  var sales;
  tables month, sum*sales;
run;
--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
ballardw
Super User

First make sure your format definition is correct. You are missing an = for the 10. Really a good idea to use quotes on both sides for a character format just to avoid confusion.

 

Try:

proc sort data=pt sortseq=linguistic(numeric_collation=on);
   by month;
run;
Proc tabulate data =work.pt format=dollar12.;
class  Month/order=data;
format Month $months.;
var pay ;
table pay=' '* Month=' ' ;
run;

The options on Proc sort should sort the month by numeric value not character order.

Then the option Order=data on the class says use the values as they appear in the data set.

 

Or perhaps: Formats are typically stored in a sort order (which is different than the result you want). The NOTSORTED makes them appear in order in the stored format as assigned. Then the interaction of order=data and Preloadfmt places the result in stored order. Note that preloadfmt will also produce values in the report that may not have occurred in the data if you use the Printmiss option.

proc format out=fmt;
value $months (notsorted)
1='07'
2='08'
3='09'
4='10'
5='11'
6='12'
7='01'
8='02'
9='03'
10='04'
11='05'
12='06';
run;

Proc tabulate data =work.pt format=dollar12.;
class  Month/order=data preloadfmt;
format Month $months.;
var pay ;
table pay=' '* Month=' '/printmiss ;
run;
Whitlea
Obsidian | Level 7

Both of these suggestions gave me the correct order in months on my table but they did not reorder the data. So now my table has 07-06 in months on top, but the pay data order is months 1-12 (July's pay is now January's pay). I have tried changing the order= option and different sorting options but have not been successful in reordering the data.  Do you have any other suggestions? Thank you!

Patrick
Opal | Level 21

Try if option order=formatted helps.

Patrick_0-1697851073353.png

 

ballardw
Super User

@Patrick wrote:

Try if option order=formatted helps.

Patrick_0-1697851073353.png

 


Almost certainly will have 01 02 03 ... not the 07 08 ...      05 06 OP requests.

PaigeMiller
Diamond | Level 26

By using actual numeric values (rather than character values) that are valid SAS date values, then TABULATE (and most other procedures) will put things in the desired order.

 

Actual valid SAS date values are integers that reflect the number of days since 01JAN1960.

 

So, if your months are '01JUL2022'd through '01JUN2023'd (the year chosen, 2022 and 2023 is irrelevant, you can pick any year) then TABULATE will order these in the desired order without much effort at all, and you can format them any way you want (such as JUL2022, or 202207 or 07 or ...). You would need to use the option ORDER=UNFORMATTED in TABULATE.

 

Any time you turn calendar information into character strings, you will have this problem. The solution is to ALWAYS (that's 100% of the time, no exceptions) work with calendar information as valid SAS date values.

--
Paige Miller

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 799 views
  • 2 likes
  • 5 in conversation