Turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- Home
- /
- Programming
- /
- SAS Procedures
- /
- proc format cntlin

Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

🔒 This topic is **solved** and **locked**.
Need further help from the community? Please
sign in and ask a **new** question.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Posted 05-23-2018 01:01 PM
(1317 views)

Dear All,

I created this format from an existing sas data set and use it to format another data set. However, it didn't populate the correct numbers of columns that I suppose to have. Thanks so much.

DATA CNTL(KEEP=START LABEL FMTNAME TYPE HLO);

SET data1;

IF _N_ = 1 THEN DO;

FMTNAME = 'MATRIX';

TYPE = 'C';

HLO = 'O';

START = ' ';

LABEL = '???';

OUTPUT;

HLO = ' ';

RETAIN HLO FMTNAME TYPE;

END;

START = FORM || ITEM_SEQ;

LABEL = PUT(POSITION,Z3.);

OUTPUT;

RUN;

PROC FORMAT CNTLIN=CNTL;

RUN;

------

DATA data3 (DROP=LOOKUP RETURNED_VALUE SLOT ISUB);

SET data2;

LENGTH M1-M&MATRIX_SLOTS. $ 1;

ARRAY ITEM (*) S1-S&ITEMS.;

ARRAY MATRIX (*) M1-M&MATRIX_SLOTS.;

DO ISUB = 1 TO &ITEMS.;

LOOKUP = FORM || PUT(ISUB,Z2.);

RETURNED_VALUE = PUT(LOOKUP,$MATRIX.);

IF RETURNED_VALUE = '???' THEN DO;

FILE PRINT;

PUT '**** ERROR ' LOOKUP=;

END;

ELSE DO;

SLOT = INPUT(RETURNED_VALUE,3.);

MATRIX(SLOT) = ITEM(ISUB);

END;

END;

OUTPUT;

RUN;

------------------log------------------------------------------------------

416 DATA data3 (DROP=LOOKUP RETURNED_VALUE SLOT ISUB);

417 SET data2;

418 LENGTH M1-M&MATRIX_SLOTS. $ 1;

SYMBOLGEN: Macro variable MATRIX_SLOTS resolves to 104

419 ARRAY ITEM (*)

419! S1-S&ITEMS.;

SYMBOLGEN: Macro variable ITEMS resolves to 30

420 ARRAY MATRIX (*)

420! M1-M&MATRIX_SLOTS.;

SYMBOLGEN: Macro variable MATRIX_SLOTS resolves to 104

421 DO ISUB = 1 TO &ITEMS.;

SYMBOLGEN: Macro variable ITEMS resolves to 30

422 LOOKUP = FORM || PUT(ISUB, Z2.);

423 RETURNED_VALUE = PUT(LOOKUP,$MATRIX.);

424 IF RETURNED_VALUE = '???' THEN DO;

425 FILE PRINT;

426 PUT '**** ERROR ' LOOKUP=;

427 END;

428 ELSE DO;

429 SLOT = INPUT(RETURNED_VALUE,3.);

430 MATRIX(SLOT) = ITEM(ISUB);

431 END;

432 END;

433 OUTPUT;

434 RUN;

1 ACCEPTED SOLUTION

Accepted Solutions

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

What does this piece of code do?

RETURNED_VALUE = PUT(LOOKUP,$MATRIX.);

If the actual value of LOOKUP is "0101" then it writes the formatted value using the format, in this case "001" into the variable Returned_value. By default Returned_value would be a character variable. If not previously defined or had a length assigned it would have length as assigned the first time that line of code executes.

What values do you have for "form" in your original data?

There are reasons we recommend providing some example data, preferably as a data step so can create a set to work with. And also provide what you expect for output.

You have do loop that would result in only the value of Returned_value remaining in the data set of the last "item" examined.

It appears you are attempting to use someone else's code. I might suggest instead of building a format that you use to make a string value that is then used with an input to get the numeric value that you create an informat to create the numeric value from. A brief example with an intentional call to a value not provided which generates an error and diagnostics:

proc format library=work; invalue matrix '0101' = 1 '0102' = 2 '0103' = 3 other=_error_; run; data example; input form $; do i= 1 to 4; slot = input( cats(form,put(i,z2.) ),matrix. ); output; end; datalines; 01 ; run;

You may have other issues related to the sizes of your arrays. The macro variable &items resolves to 40 and &Matrix_slots=104.

So the largest number of matrix variables that would be assigned values in this case is likely 40 on any row of data.

Did you get this code to work without any macro variables? With a data set data2 with only a few records and few variables to verify that the logic worked for a known case?

And if the whole purpose of this is to find which element of an array has a specific value then there are two functions, depending on whether the value is numeric or character that will do that:

slot = Whichc ('0101', of item(*) ); would return the first position of '0101' in the array item.

Without a little more concrete as to what is actually in your data set, variable values and types and actual desired result I'm not sure what else I might be able to provide in the way of assistance.

3 REPLIES 3

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

I am not seeing how you expect a FORMAT to have anything to do with "the correct numbers of columns". A Format only controls how values are displayed.

The only place I see you using the format is in this line:

RETURNED_VALUE = PUT(LOOKUP,$MATRIX.);

How would that control the number of columns? Or is the returned value unexpected?

Be aware that this line:

LOOKUP = FORM || PUT(ISUB,Z2.);

may be creating values of LOOKUP different that you expect:

Please consider this code:

data example; input form $; isub= 4; lookup = form||put(isub,z2.); datalines; a ab abc abcd ; run;

where lookup has differing numbers of spaces between the Form and the two digits.

Perhaps what you are looking for is

lookup = cats( form,put(isub,z2.));

which removes any trailing blanks from Form before appending the two digits.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Thank you ballardw for your reply. It makes sense. However, It didn't work after changing to

lookup = cats( form,put(isub,z2.));

What does this piece of code do?

RETURNED_VALUE = PUT(LOOKUP,$MATRIX.);

The matrix format looks like this

SAS Output

Obs | FMTNAME | TYPE | HLO | START | LABEL |
---|---|---|---|---|---|

1 | MATRIX | C | O | ??? | |

2 | MATRIX | C | 0101 | 001 | |

3 | MATRIX | C | 0102 | 002 | |

4 | MATRIX | C | 0103 | 003 | |

5 | MATRIX | C | 0104 | 004 |

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

What does this piece of code do?

RETURNED_VALUE = PUT(LOOKUP,$MATRIX.);

If the actual value of LOOKUP is "0101" then it writes the formatted value using the format, in this case "001" into the variable Returned_value. By default Returned_value would be a character variable. If not previously defined or had a length assigned it would have length as assigned the first time that line of code executes.

What values do you have for "form" in your original data?

There are reasons we recommend providing some example data, preferably as a data step so can create a set to work with. And also provide what you expect for output.

You have do loop that would result in only the value of Returned_value remaining in the data set of the last "item" examined.

It appears you are attempting to use someone else's code. I might suggest instead of building a format that you use to make a string value that is then used with an input to get the numeric value that you create an informat to create the numeric value from. A brief example with an intentional call to a value not provided which generates an error and diagnostics:

proc format library=work; invalue matrix '0101' = 1 '0102' = 2 '0103' = 3 other=_error_; run; data example; input form $; do i= 1 to 4; slot = input( cats(form,put(i,z2.) ),matrix. ); output; end; datalines; 01 ; run;

You may have other issues related to the sizes of your arrays. The macro variable &items resolves to 40 and &Matrix_slots=104.

So the largest number of matrix variables that would be assigned values in this case is likely 40 on any row of data.

Did you get this code to work without any macro variables? With a data set data2 with only a few records and few variables to verify that the logic worked for a known case?

And if the whole purpose of this is to find which element of an array has a specific value then there are two functions, depending on whether the value is numeric or character that will do that:

slot = Whichc ('0101', of item(*) ); would return the first position of '0101' in the array item.

Without a little more concrete as to what is actually in your data set, variable values and types and actual desired result I'm not sure what else I might be able to provide in the way of assistance.

**SAS Innovate 2025** is scheduled for May 6-9 in Orlando, FL. Sign up to be **first to learn** about the agenda and registration!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

Find more tutorials on the SAS Users YouTube channel.

Ready to level-up your skills? Choose your own adventure.