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

Hello

 

I am using SAS9.4 on  a Windows10 PC environment.

 

I am trying to create a string column to contain a full description by using a format within a PUT statement.  I want the format name to be generated dynamically based on a value in a different column.   This seems feasible but I can't quite nail it, example program attached.

 

I have this problem on a couple of programs so all help will be gratefully received, thank you.

1 ACCEPTED SOLUTION

Accepted Solutions
rogerjdeangelis
Barite | Level 11
/* T1002580 Using putc or putn with format names in your data

Using putc or putn with format names in your data

This seems to work

inspired by
https://goo.gl/ktxY1O
https://communities.sas.com/t5/Base-SAS-Programming/Dynamic-apply-format-by-making-the-fmtname-from-a-value-in-the/m-p/335244

HAVE
====

proc format;
      value $ FMTA1X
      "A" = "this was discount $10"
      "B" = "this was discount $20"
      ;

      value $ FMTA2X
      "A" = "this was discount $300"
      "B" = "this was discount $400"
            ;
run;

Up to 40 obs WORK.HAVE total obs=5

Obs    PRODTYPE    DISCOUNT

 1        A1          B
 2        A2          A
 3        A2          A
 4        A2          B
 5        A1          B

WANT
====

Up to 40 obs WORK.DEMO_DESCRIPTION_HARDCODE total obs=5

Obs    PRODTYPE    DISCOUNT        DISCOUNT_DESC

 1        A1          B        this was discount $20   putc(discount,$fmta1x.)
 2        A2          A        this was discount $300
 3        A2          A        this was discount $300
 4        A2          B        this was discount $400
 5        A1          B        this was discount $20


SOLUTION
========

data have;
input Prodtype $ Discount $;
cards4;
A1 B
A2 A
A2 A
A2 B
A1 B
;;;;
run;quit;

data want;
  retain prodtype discount discount_desc;
  length discount_desc $44;
  set have;

  fmt=cats('$fmt',prodtype,'x');
  Discount_desc = putc(Discount,fmt);

run;quit;


Up to 40 obs WORK.WANT total obs=5

Obs    PRODTYPE    DISCOUNT        DISCOUNT_DESC           FMT

 1        A1          B        this was discount $20     $fmtA1x
 2        A2          A        this was discount $300    $fmtA2x
 3        A2          A        this was discount $300    $fmtA2x
 4        A2          B        this was discount $400    $fmtA2x
 5        A1          B        this was discount $20     $fmtA1x

View solution in original post

6 REPLIES 6
Kurt_Bremser
Super User

Not possible.

The format is set when the data step is compiled, so formats need to be named literally.

From the documentation of the put() function:

format.

contains the SAS format that you want applied to the value that is specified in the source. This argument must be the name of a format with a period and optional width and decimal specifications, not a character constant, variable, or expression.

(Emphasis by me)

 

Read the documentation.

 

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Post your examples as text in a code window ({i} above post).  Is there a reason you want to try to automate it, you will need to have the list somewhere if so.  If its just a couple then what you have is fine.  To automate will take more code:

data fmts;
  length fmt_cond fmt $200;
  input fmt_cond $ fmt $;
datalines;
A1 $fmt2
A2 $fmt1
;
run;

data _null_;
  set fmts  end=last;
  if _n_=1 then call execute('data want;  set have;');
  call execute('if variable="'||strip(fmt_cond)||'" then res=put(   ...);
  if last then call execute('run;');
run;

Just as an example, however I would really question why this is necessary at all.

Reeza
Super User

PUTC/PUTN allow format names that are from a variable. 

 

Borrowing code:

 

data fmts;
length fmt_cond fmt $200;
input fmt_cond $ fmt $;
datalines;
A1 $fmt2
A2 $fmt1
;
run;

 

Data want;

set fmts;

 

want_var = putc(fmt_cond, fmt);

Run;

mkeintz
PROC Star

I suspect you would also be well served by a hash lookup table, keyed on 2 vars: PRODTYPE and DISCOUNT.  Make a lookup dataset, with all the expected combinations of prodtype,discount, and discount_desc.  Then load it into a hash object to use in the data step:

 

data lookup;
  input  prodtype :$2. discount :$1. @6 discount_desc $30.;
datalines;
A1 A this was discount $10
A1 B this was discount $20
A2 A this was discount $300
A2 B this was discount $400
run;

data demo_description_dynamic (drop=rc);
  set demodata;
  if _n_=1 then do;
    if 0 then set lookup;
    declare hash h (dataset:'lookup');
      h.definekey('prodtype','discount');
      h.definedata(all:'Y');
      h.definedone();
  end;
  rc=h.find();
  if rc^=0 then call missing(discount_desc);
run;

 

When the h.find() method is successful, two things happen:  RC=0 and discount_desc is retrieved from the desired item in hash object h.  If it's unsuccessful, RC ^=0 and discount_desc is unchanged from the last successful h.find().  That's why you see discount_desc set to missing when rc^=0.

--------------------------
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

--------------------------
rogerjdeangelis
Barite | Level 11
/* T1002580 Using putc or putn with format names in your data

Using putc or putn with format names in your data

This seems to work

inspired by
https://goo.gl/ktxY1O
https://communities.sas.com/t5/Base-SAS-Programming/Dynamic-apply-format-by-making-the-fmtname-from-a-value-in-the/m-p/335244

HAVE
====

proc format;
      value $ FMTA1X
      "A" = "this was discount $10"
      "B" = "this was discount $20"
      ;

      value $ FMTA2X
      "A" = "this was discount $300"
      "B" = "this was discount $400"
            ;
run;

Up to 40 obs WORK.HAVE total obs=5

Obs    PRODTYPE    DISCOUNT

 1        A1          B
 2        A2          A
 3        A2          A
 4        A2          B
 5        A1          B

WANT
====

Up to 40 obs WORK.DEMO_DESCRIPTION_HARDCODE total obs=5

Obs    PRODTYPE    DISCOUNT        DISCOUNT_DESC

 1        A1          B        this was discount $20   putc(discount,$fmta1x.)
 2        A2          A        this was discount $300
 3        A2          A        this was discount $300
 4        A2          B        this was discount $400
 5        A1          B        this was discount $20


SOLUTION
========

data have;
input Prodtype $ Discount $;
cards4;
A1 B
A2 A
A2 A
A2 B
A1 B
;;;;
run;quit;

data want;
  retain prodtype discount discount_desc;
  length discount_desc $44;
  set have;

  fmt=cats('$fmt',prodtype,'x');
  Discount_desc = putc(Discount,fmt);

run;quit;


Up to 40 obs WORK.WANT total obs=5

Obs    PRODTYPE    DISCOUNT        DISCOUNT_DESC           FMT

 1        A1          B        this was discount $20     $fmtA1x
 2        A2          A        this was discount $300    $fmtA2x
 3        A2          A        this was discount $300    $fmtA2x
 4        A2          B        this was discount $400    $fmtA2x
 5        A1          B        this was discount $20     $fmtA1x
RB1Kenobi
Quartz | Level 8

Thank you all for your contributions. 

The other way I was looking at the problem was to use create a function (Proc FCMP) which would have been stored in one place and then reference across the different programs.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 2466 views
  • 2 likes
  • 6 in conversation