用sas替换列中的字符串

问题描述 投票:-2回答:1

我想用以下内容替换列中的所有字符串:

strings  new_strings
ABC_MNO_S3  S1
ABC_S1      S2
ABC_S2      S3
ABC_PQR_S3  S4
XYZ_MNO_S3  S5
XYZ_S1      S6
XYZ_S2      S7
XYZ_PQR_S3  S8

因此,无论何时上述“字符串”出现在我的列“状态”中,我都希望动态地将其替换为“new_string”。我试图将这些列表放在一个数组中,并使用TRANWRD搜索列并替换,但不能正常工作。

我的列说明了所需的输出如下所示:

states                 states_result
TR_ABC_MNO_S3_ABC_S2    TR_S1_S3
TR_ABC_S1_ABC_S2        TR_S2_S3
Segment                 Segment
ABC_PQR_S3              S4
TR_XYZ_MNO_S3_XYZ_S2    TR_S5_S7
Year                    Year
St_XYZ_S2               St_S7

能否请你帮忙?谢谢!

arrays sas datastep
1个回答
1
投票

Sourav:

因为你提到TRANWRD我会假设strings值可以嵌入在states值中。有效使用TRANWRD的关键是TRIM当变量用于目标和替换参数时的值。

更换问题:

  • 如果仅嵌入一个目标值,则单独使用TRANWRD将起作用。
  • 如果可以嵌入多个目标值,则需要在所有目标上进行循环。

早期的替换可能会成为一个以前不明显的有效替代品。考虑以下state值:

ABC_ABC_MNO_S3

所有目标的第一个循环将用ABC_MNO_S3和yield替换S1

ABC_S1

所有目标上的第二个循环将用ABC_S1和yield替换S2

S2

经过测试的样本:

data have;
infile cards dlm="," dsd;
length states segment year $100;
input states segment year;
datalines;
"TR_ABC_MNO_S3_ABC_S2 TR_ABC_S1_ABC_S2", "ABC_PQR_S3 TR_XYZ_MNO_S3_XYZ_S2", "St_XYZ_S2"
run;

data mappings;
length string $30 new_string $2;
input string new_string;
datalines;
ABC_MNO_S3  S1
ABC_S1      S2
ABC_S2      S3
ABC_PQR_S3  S4
XYZ_MNO_S3  S5
XYZ_S1      S6
XYZ_S2      S7
XYZ_PQR_S3  S8
run;

data want;
  array maps(100,2) $50 _temporary_; * first dimension must be larger than number of mappings;
  do _i_ = 1 by 1 until (lastmap);
    set mappings(rename=(string=_map_from new_string=_map_to)) end=lastmap;
    maps(_i_,1) = _map_from;
    maps(_i_,2) = _map_to;
  end;

  length status $12 _result $200;

  do until (lastdata);

    set have end=lastdata;
    array targets states segment year;

status = 'ORIGINAL'; 
output;

    do _i_ = 1  to dim(targets);

      _result = targets[_i_];
      _guard = 1;
      do until (_noreplacement or _guard >= 10);
        _noreplacement = 1;
        do _j_ = 1 to dim(maps,1) while(maps(_j_,1) ne '');
          if index(_result,trim(maps(_j_,1))) then do;

* put _result ': ' maps(_j_,1) '-> ' maps(_j_,2);

            _result = tranwrd(_result, trim(maps(_j_,1)), trim(maps(_j_,2)));
            _noreplacement = 0;
          end;
        end;
      end;

      if (_guard > 10) then do;
        put 'WARNING: Guard limit 10 reached, mappings may be cycling.' _result;
      end;

      targets[_i_] = _result;
    end;

    status = 'MAPS APPLIED';
    output;
  end;

  stop;
  drop _:;
run;
© www.soinside.com 2019 - 2024. All rights reserved.