Help using Base SAS procedures

proc format cntlin

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 13
Accepted Solution

proc format cntlin

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;


Accepted Solutions
Solution
‎05-24-2018 08:02 PM
Super User
Posts: 13,498

Re: proc format cntlin

[ Edited ]

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.

View solution in original post


All Replies
Super User
Posts: 13,498

Re: proc format cntlin

[ Edited ]

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.

 

Occasional Contributor
Posts: 13

Re: proc format cntlin

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
Solution
‎05-24-2018 08:02 PM
Super User
Posts: 13,498

Re: proc format cntlin

[ Edited ]

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.

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 3 replies
  • 185 views
  • 0 likes
  • 2 in conversation