【问题标题】:How do I assign numeric values to the alphabet in SAS如何将数值分配给 SAS 中的字母表
【发布时间】:2012-12-07 16:41:19
【问题描述】:

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

在此先感谢...感谢任何帮助或建议。 -雷切尔

【问题讨论】:

    标签: sas


    【解决方案1】:

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

    所以这应该可以工作(如果你只想要大写的值 - 不是 a 与 A 不同的值):

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

    另一个选项(基于下面的 cmets)是建立一个包含字母和值之间关系的信息。我的循环遍历每个字符 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;
    

    最后,如果您希望能够在 same 数据步中构造它,您可以在哈希表中构造关系并查找结果。如果需要,我可以解释一下,不过我希望看到一个更详细的示例,说明您在定义字母与其代码之间的关系方面想要做什么。

    如果您需要查看中间值,可以通过在循环中插入 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;
    

    【讨论】:

    • 谢谢,但我特别想将值分配给字母,如上所述,或者我可能想修改模式,比如,
    • 这个 A=n(n-1)/2 ...所以重要的是 A=1 和 B=2 等等。
    【解决方案2】:

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

    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 变量,我在原始问题中忽略了它。

    【讨论】:

    • 我建议使用 CATX 功能,而不是那种复杂的修剪/||东西。
    • @Joe:我很高兴看到一个使用 CATX 构建每个字符之间有空格的新字符串的示例。 CHAR_2_NUM = catx(CHAR_2_NUM, ' ', substr(MY_VAR_CHAR,i,1)); 不起作用。
    • 参见我上面的解决方案(在第二个到最后一个块中):) CATX 将其第一个参数作为分隔符,因此 CATX(' ',str1,str2,str3,...) 将分隔各种带空格的字符串。
    • 乔,你真棒!代码效果很好。再次感谢您...非常感谢。
    • Rachel,你应该看看 SOUNDEX 函数,然后(或类似的 - SAS 有几个)。在文档中查找。它基本上执行您描述的功能。
    【解决方案3】:

    另一个简单的解决方案是基于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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-17
      • 2018-04-18
      • 2016-02-17
      • 1970-01-01
      相关资源
      最近更新 更多