BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
ProtoLithic
Calcite | Level 5

Hi,

 

Just wondering if it is possible to format a numeric based on values of specific digits in a PROC FORMAT?

 

For example, would it be possible to format these numbers based on the coloured digits only without a data step to split them out first? (for example, the thousands values, irrespective of what the other values are... is there a wildcard type approach?) 

 

501210

701304

 

I'm aware how to do this in a data step but, having just concatenated the variables for efficiency, I don't want to split them back out for formatting.

 

EDIT: Adding context that I should have included in the first place!

 

The format of the variable could be either numeric or character - either works for my purposes, by character is easier. The use of the format would for grouping in a class in a PROC TABULATE. Definitely not in a PUT statement as I don't want to split the data back out.

For further context ... as an example, if my data has many variables in one row like: Value_at_8am [2 digits], Value_at_9am [2 digits], Value_at_10am [2 digits] ... and I concatenate them, can I then have a format that classifies based on the Value_at_9am in the new concatenated string irrespective of the value that come before or after it in the concatenated string?

 

So, Ideally, I have a concatenated string when any range 01-99 in the 3rd and 4th places could be formatted to "True":

Proc Format

Value wishful

 **01** - **99** = "Value at 9am is True"

**00** = "Value at 9am is False"

****01-****99 = "Value at 10 am is True"

... etc.

 

 

cheers.

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

I might just be easiest to make your format from your data.  So if your data looks like this:

data have;
  input string $10. @1 number ;
cards;
501210
701304
600055
;

You could convert numeric variable NUMBER to the middle two digits by a formula like this:

data want;
  set have;
  want1 = int(mod(number,10**4)/10**2);
run;

So use that to make a CNTLIN dataset to define your name format. Let's call it V9AM.

proc sql ;
create table cntlin as
  select distinct
         'V9AM' as fmtname 
       , number as start
       , int(mod(number,10**4)/10**2) as v9AM
       , case when (calculated v9am = 0) then 'Value at 9am is False' else 'Value at 9am is True' end as label
  from have 
  order by 1,2
;
quit;
proc format cntlin=cntlin; run;

Now you can use that format in your code:

proc print data=have ;
   format number v9am. ;
run;
Obs    string           number

 1     501210    Value at 9am is True
 2     701304    Value at 9am is True
 3     600055    Value at 9am is False

View solution in original post

5 REPLIES 5
Tom
Super User Tom
Super User

What type variable/format are you looking for here. Numeric or Character?  Is your variable numeric or character?

 

Please explain what values you want be displayed by the format?  For example show what displayed value you want for the stored values you showed.

 

How are you going to use this format?  Just for printing the output? For grouping , like in a CLASS variable? For making a new variable with the PUT() function?

CurtisMackWSIPP
Lapis Lazuli | Level 10

There may be other ways, but I know PROC FCMP will get your there:

 

DATA raw;
  INFILE DATALINES;
  INPUT myval $6.;
DATALINES;
501210
701304
;
run;


proc fcmp outlib=work.functions.fun; 
   function mask(string $) $;
      return (substr(string,3,2));
   endsub;
run;

options cmplib=work.functions;
proc format;
    value $ mask (default=200) other=[mask()];
    value $ masky '11' = 'Eleven' 
                  '12' = 'Twelve'
                  '13' = 'Thirteen';
run;

data results;
  set raw;
  formated = put(put(myval,$mask.),$masky.);
run;
CurtisMackWSIPP
Lapis Lazuli | Level 10

I realized you wanted a numeric format.  Its a simple fix:

 

DATA raw;
  INFILE DATALINES;
  INPUT myval 8.;
DATALINES;
501210
701304
;
run;


proc fcmp outlib=work.functions.fun; 
   function mask(num_in) $;
      return (substr(put(num_in,Z6.),3,2));
   endsub;
run;

options cmplib=work.functions;
proc format;
    value  mask (default=200) other=[mask()];
    value $ masky '11' = 'Eleven' 
                  '12' = 'Twelve'
                  '13' = 'Thirteen';
 
run;

data results;
  set raw;
  formated = put(put(myval,mask.),$masky.);
run;
Tom
Super User Tom
Super User

I might just be easiest to make your format from your data.  So if your data looks like this:

data have;
  input string $10. @1 number ;
cards;
501210
701304
600055
;

You could convert numeric variable NUMBER to the middle two digits by a formula like this:

data want;
  set have;
  want1 = int(mod(number,10**4)/10**2);
run;

So use that to make a CNTLIN dataset to define your name format. Let's call it V9AM.

proc sql ;
create table cntlin as
  select distinct
         'V9AM' as fmtname 
       , number as start
       , int(mod(number,10**4)/10**2) as v9AM
       , case when (calculated v9am = 0) then 'Value at 9am is False' else 'Value at 9am is True' end as label
  from have 
  order by 1,2
;
quit;
proc format cntlin=cntlin; run;

Now you can use that format in your code:

proc print data=have ;
   format number v9am. ;
run;
Obs    string           number

 1     501210    Value at 9am is True
 2     701304    Value at 9am is True
 3     600055    Value at 9am is False

ProtoLithic
Calcite | Level 5
This is genius, thanks. But will is run into issues if the dataset is large (many combinations)? Will the format be too cumbersome?

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 5 replies
  • 1542 views
  • 1 like
  • 3 in conversation