SAS:前导零并用负数值代替数字中的字母

时间:2015-06-27 19:10:46

标签: debugging sas

我的列中包含带前导零的数字。有些数字在末尾有字母表,如(00054A)表示特定值。我需要删除前导零并用值替换字母表。有些字母有负值,当我使用函数(TRANSTRN / TRANWRD)替换时,只有连字符被替换,值看起来像(000123-)。在删除前导零之后,我希望此负号位于数字的前面。由于在需要替换的6-8个不同列上存在值为(-12到+12)的字母,因此如果用宏写入它会更好吗?我应该使用什么函数来删除前导零并用负值代替字母?

数据:

0830 4368 0000856A

0177 7520 0001299K

代码:

    data text1;
    infile "/location/file.txt";
    input VariableX $1-4 VariableY $5-8 VariableC $9-16
    run;    

    data text2;
    set text1;
    VariableC=TRANWRD(VariableC, 'A', '1'); 
    VariableC=TRANWRD(VariableC, 'K', '-2');
    run;

输出:

   0830 4368 00008561
   0177 7520 0001299-

预期产出:

   0830 4368 8561
   0177 7520 -12992

3 个答案:

答案 0 :(得分:0)

   data test;
   input VariableC $ 10.;
   posit =0;
   if substr(VariableC,2,2) = "00" then do;  <== not to process value with less than two trailing zero 
      x =1 ;
      do while (x ^=0 );
         posit +1;
         x=find(VariableC,"0", posit );  <== find where is the last zero.
         if ( x - posit  ) > 1 then x =0; <== Avoid finding '0' between non-zero number 
                                             and the end of expression
      end;

   subNewVariableC = substr(VariableC, posit   );
   end;

   if find( subNewVariableC, "A", -1 ) = 1 then 
      NewVariableC=TRANWRD( subNewVariableC, 'A', '1'); 

   if find(subNewVariableC, "K",-1) = 1 then do;
      NewVariableC=TRANWRD( subNewVariableC, 'K', '2');
      NewVariableC = trim("-") !! trim(NewVariableC); 
   end;   
   drop posit x subNewVariableC VariableC;    
   datalines;
   ...
   run;

它会做你所期望的。

与此同时,我正在寻找好的解决方案,以便我也可以学习......

答案 1 :(得分:0)

我的偏好是以格式存储每个字母的值(实际上是一个信息,因为它使代码更容易,但原理是相同的)。然后将其用作查找以将字母转换为数字。

我将多个功能合并为一行,这使得它很长,其逻辑如下

  • 提取数字部分
  • 提取字母,转换为所需的数字(不带标志)并附加到已提取的数字部分
  • 使用input函数
  • 转换为数字类型
  • 将新创建的数字乘以字母查找值的符号。 sign函数返回-1表示负值,1表示正值,0表示0。为了避免乘以0,我已经添加了一个来制作这个1。
  • 将此数字转换回字符值,并左对齐以删除前导空格

希望这是有道理的,这是代码。

/* create lookup informat */
proc format;
    invalue  letter 'A' = 1
                    'K' = -2;
run;

/* dummy dataset */
data have;
input x $ y $ c$ :15.;
datalines;
0830 4368 0000856A
0177 7520 0001299K
;
run;

/* transformed values */
data want;
set have;
c1 = left(put(input(
                    cats( compress(c,,'kd'), /* keep numbers */
                          abs(input(compress(c,,'ka'),letter.))) /* keep letter, convert to number (without the sign) and append to numbers */ 
              ,best12.)
                    *ifn(input(compress(c,,'ka'),letter.)=0,1,sign(input(compress(c,,'ka'),letter.))) /* multiply by sign of letter lookup number (if 0 then multiply by 1) */
         ,best12.));
run;

答案 2 :(得分:0)

如果A和K是您需要注意的唯一场景,那么PRX功能可以按旧学期条款(如果......那样)提供:

/* dummy dataset */
data have;
    input x $ y $ c$ :15.;
    datalines;
0830 4368 0000856A
0177 7520 0001299K
;
run;

data want;
    set have;

    if strip(reverse(c)) =:'A' then
        do;
            c=prxchange('s/A$/1/',-1, trim(c)); /*if the last char is A, first replace A with 1*/
            c=prxchange('s/^0*//',-1, trim(c)); /* Second replace the leading 0s with nothing*/
        end;
    else if strip(reverse(c)) =:'K' then
        do;
            c=prxchange('s/K$/2/',-1, trim(c)); /*If the last char is K, first replace K with 2*/
            c=prxchange('s/^0*/-/',-1, trim(c)); /*second replace the leading 0s with -*/
        end;
run;