如何为SAS中的字母分配数值

时间:2012-12-07 16:41:19

标签: sas

我正在尝试将字符串转换为数字变量,然后将每个字符的值相加以用作该字段的唯一标识符。 因此,例如,我希望A = 1,B = 2,C = 3 ...... X = 24 Y = 25 Z = 26。 假设我的字符串是“CAB”所以在运行代码之后我希望结果是一个数字的中间列,其中CAB的值为3 1 2,结果列将通过对字符串3 + 1 + 2求和得出= 6并显示intermideate列的值,因此最终值为6。

以下是我用来将字符转换为数字的sas代码,但我需要有关结果列的帮助。

DATA CHAR_VALUE;
SET WORK.XYZ;
CHAR_2_NUM=TRANSLATE(MY_VAR_CHAR, '1 2 3 ...24 25 26', 'A B C ...X Y Z');
NUM_CHAR=INPUT(CHAR_2_NUM,32.);
RUN;

提前致谢...我感谢任何帮助或建议。 -rachel

3 个答案:

答案 0 :(得分:2)

RANK将给出字符下面的ASCII数值;所以A = 65,B = 66,Z = 90,a = 97,z = 122。

所以这应该有效(如果你只想要大写的值 - 而不是A的不同值):

data test;
charval='CAB';
do _t=1 to length(Charval);
    numval=sum(numval,rank(char(upcase(charval),_t))-64);
end;
put _all_;
run;

另一个选项(基于下面的评论)是建立一个包含字母和值之间关系的信息。我的循环遍历每个字符A到Z,然后你可以为每个字母添加你想要的任何值作为标签(我只是放1,2,3,4 ......但label =会改变它)。

data fmts;
retain fmtname 'CHARNUM' type 'i';
do _t=65 to 90;
start=byte(_t); *the character, so byte(65)='A';
label=_t-64;    *the resulting number;
output;
end;
run;
proc format cntlin=fmts;
quit;

data test;
charval='CAB';
do _t=1 to length(Charval);
    numval=sum(numval,input(char(upcase(charval),_t),CHARNUM.));
end;
put _all_;
run;

最后,如果您希望能够在相同的 datastep中构造它,您可以在哈希表中构建关系并查找结果。我可以解释一下,如果需要,虽然我想看一个更详细的例子,说明你想要在定义字母和代码之间的关系方面做些什么。

如果你需要查看中间值,可以通过在循环中插入CAT函数来实现 - 我推荐CATX:

data test;
charval='CAB';
format intermed $100.;
   do _t=1 to length(Charval);
        numval=sum(numval,input(char(upcase(charval),_t),CHARNUM.));
        intermed=catx('|',intermed,input(char(upcase(charval),_t),CHARNUM.)); *or the RANK portion from earlier;
    end;


put _all_;
run;

这会给你3|1|2,你可以通过SCAN进行数学运算:

do _t = 1 to countc(intermed,'|')+1;
  numval2 = sum(numval2,scan(intermed,_t,'|'));
end;

答案 1 :(得分:0)

尝试翻译的方法是一个很好的尝试,但它不会真正起作用。这是一个简单的解决方案:

DATA CHAR_VALUE;
  retain all_chars 'ABCDEFGHIJKLMMOPQRSTUVXXYZ';
  set XYZ;

  length CHAR_2_NUM $200;
  CHAR_2_NUM = ' ';
  NUM_CHAR = 0;

  do i=1 to length(MY_VAR_CHAR);
     if i=1 then CHAR_2_NUM = substr(MY_VAR_CHAR,i,1);
            else CHAR_2_NUM = trim(CHAR_2_NUM) || ' ' || substr(MY_VAR_CHAR,i,1);
     NUM_CHAR + index(all_chars,substr(MY_VAR_CHAR,i,1));
     end;
  drop i all_chars;
RUN;

这利用了all_chars变量中源变量的每个字符的索引位置对应于您所需的映射这一事实。

更新以创建您的CHAR_2_NUM变量,我在原始问题中忽略了该变量。

答案 2 :(得分:0)

另一个简单的解决方案基于collate函数:

要将名为MyNumbers(在1到26之间)的变量转换为英文大写字母,可以使用:

collate(64 + MyNumbers, 64 + MyNumbers)

要获取小写字母,可以使用:

collate(96 + MyNumbers, 96 + MyNumbers)

这是一个简单的例子:

data _null_;
    do MyNumbers = 1 to 26;
          MyLettersUpper = collate(64 + MyNumbers, 64 + MyNumbers);
          MyLettersLower = collate(96 + MyNumbers, 96 + MyNumbers);
          put MyNumbers MyLettersUpper MyLettersLower;
    end;
run;

    1 A a
    2 B b
    3 C c
    4 D d
    5 E e
    6 F f
    7 G g
    8 H h
    9 I i
    10 J j
    11 K k
    12 L l
    13 M m
    14 N n
    15 O o
    16 P p
    17 Q q
    18 R r
    19 S s
    20 T t
    21 U u
    22 V v
    23 W w
    24 X x
    25 Y y
    26 Z z
    NOTE: DATA statement used (Total process time):
          real time           0.03 seconds
          cpu time            0.03 seconds