This should be simple, but I just can't see it.
What is the best way to replicate the functionality of the data-step RANK function from within IML?
Using syntax such as rank('G') results in the error, "Character operation not implemented yet", which I presume is referring to the IML RANK function not being able to handle a character matrix.
Thanks,
Ian.
Another way to do it would be to use the pib1. format.
n = inputn("A","pib1.");
Hi Ian,
You might find the following link interesting.
Specifically the section referring to the following code.
/* Create RANK-like functionality for character matrices */
start rankc(x);
s = unique(x); /* the unique function returns a sorted list */
idx = j(nrow(x), ncol(x));
ctr = 1; /* there can be duplicate values in x */
do i = 1 to ncol(s); /* for each unique value */
t = loc(x = s);
nDups = ncol(t);
idx
ctr = ctr + nDups;
end;
return (idx);
finish;
/* call the RANKC module */
x = {every good boy does fine and good and well every day};
rc = rankc(x);
print rc[colnam=x];
/* Notice that ranking is in ASCII order, in which capital
letters precede lower case letters. To get case-insensitive
behavior, transform the matrix before comparison */
x = {"a" "b" "X" "Y" };
asciiOrder = rankc(x);
alphaOrder = rankc(upcase(x));
print x, asciiOrder, alphaOrder;
Hi Scott,
Thanks, but I am not looking to get the rank order of all the elements in a character matrix. In a data-step rank('G') returns 71, the character code for the letter G, I am looking for the equivalent of that in IML.
You title suggests that you want to find the ascii code. Try this:
ascii = byte(65:122);
label = "A65":"A122";
print ascii[colname=label];
Thanks Rick,
I have gone with
start char_rank(c);
ascii = byte(65:122);
return( loc( ascii = c) + 64);
finish;
it will work for what I have in mind as I know c will always be a single letter. I was kind of hoping that since BYTE was available, then there should be a way to get the inverse function.
Ian.
Sounds good. Here's a cute idea that falls into the "isn't that interesting" category. It maps each alphabetical value (no punctuation) to the ascii code for the uppercase version of the letter:
asciiVals = 65:90;
letters = byte(asciiVals);
mattrib asciiVals colname=letters;
str = {I A N W A K E L I N G};
b = asciiVals[,str];
print b;
Probably not useful for your application, but fun. For more on the MATTRIB function, see Access rows or columns of a matrix by names - The DO Loop
That's a very nice and a unintended use of mattrib. Unfortunately my application has lower case letters as well otherwise I would use it.
The character data that I want to convert comes in blocks of letters without delimiters and I find that I need to chop the blocks into individual characters as you have done with my name above. There is no need to loop over each character in the string, as I have found that I can do this as follows:
start chop(s);
call execute( cat( 'chopstr = {', prxchange( "s/(.)/'$1' /", -1, s), '};') );
return(chopstr);
finish;
str=chop('IanWakeling');
print str;
By the way, it is not possible to use a call execute to return from a function module - I tried!
If you have SAS/IML 12.1, you can use a new feature of the SUBSTR function:
start chop(s);
return ( substr(s, 1:nleng(s), 1) );
finish;
That's a lot nicer, I shall have to look into upgrading.
Here's one you can use without upgrading:
start chop(s);
return( cshape(s,1,nleng(s),1) );
finish;
Thanks Rick, that's cool. I never looked at cshape before. The assumption would be that the functionality is similar to the regular shape function, but the size parameter makes it more powerful as you have shown.
Another way to do it would be to use the pib1. format.
n = inputn("A","pib1.");
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 16. Read more here about why you should contribute and what is in it for you!
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.