【问题标题】:Remove words from field using words from a table in SAS使用 SAS 表中的单词从字段中删除单词
【发布时间】:2019-08-29 13:04:32
【问题描述】:

我正在尝试使用单词表从 SAS 字段中删除单词。

我已经能够使用我在网上找到的一些代码来隔离每个单词,但我无法从字段中删除该单词。

例如,如果字段是:

“狐狸跳过月亮”

如果单词“jumped”在单词列表中,则结果应如下所示:

“月亮上的狐狸”

这是要删除的停用词表:

PROC SQL;
   CREATE TABLE BOW.QUERY_FOR_STOPWORDS AS 
   SELECT t1.StopWords
      FROM BOW.STOPWORDS t1;
QUIT;

这是需要删除字段的表格:

PROC SQL;
   CREATE TABLE WORK.QUERY_FOR_ANNU_COMMENTS AS 
   SELECT t1.Comment
      FROM BOW.ANNU_COMMENTS t1;
QUIT;

【问题讨论】:

标签: sql sas


【解决方案1】:

取决于你有多少单词有其他解决方案。

data _NULL_;
    set STOPWORDS end=e;
    if _N_=1 then call execute('data result;set ANNU_COMMENTS;newComment=Comment;');
    call execute('if _N_=1 then __'||put(_N_,z30.)||'+prxparse("s/'||trimn(StopWords)||'//");');
    call execute('call prxchange(__'||put(_N_,z30.)||',-1,newComment);');   
    if e then call execute('drop __:;run;');
run;

这将使用停用词从它生成数据步,而不是这个数据步过程 cmets。

编辑: 要仅按单词边界删除单词,您必须在正则表达式中使用 \b。

data _NULL_;
    set STOPWORDS end=e;
    if _N_=1 then call execute('data result;set ANNU_COMMENTS;newComment=Comment;');
    call execute('if _N_=1 then __'||put(_N_,z30.)||'+prxparse("s/\b'||trimn(StopWords)||'\b//");');
    call execute('call prxchange(__'||put(_N_,z30.)||',-1,newComment);');   
    if e then call execute('drop __:;run;');
run;

【讨论】:

  • 你好李,我怎样才能让它生成没有任何停用词的新字段,并将其放在评论字段旁边作为“新评论”
  • 先简单复制到新变量而不是改变它。我编辑了代码以反映这一点。
  • 我收到以下错误:582 + if _N_=1 then __0000000000000000000000000000291+prxparse("s/HERSE"//");" __ 388 76 错误 388-185:需要算术运算符。 ERROR 76-322:语法错误,语句将被忽略。
  • 注意:SAS 系统因错误而停止处理此步骤。警告:数据集 WORK.RESULT 可能不完整。当这一步停止时,有 0 个观察值和 25 个变量。警告:数据集 WORK.RESULT 未被替换,因为此步骤已停止。
  • 那是因为你的单词里面有一个"
【解决方案2】:

可以编写一个宏来生成清洗数据步骤。

这个例子融合了盛林对 tranwrd 的使用和 Lee 的 codegen。

%macro flense (
  data=Commments,
  var=Comment, 
  newvar=CommentFlensed, 
  censor=BOW.StopWordsList,
  term=StopWords
);

  proc sql noprint;
    select quote(trim(&term),"'") into :sq_word1-;  * single quote the words to prevent possible macro evaluation later;
    from &censorData;

  data &out;
    set &data;
    &newvar = &var;

    %* for each censored word, generate an if statement
     * that checks if the word (or term) is present, and if so
     * removes the word from the new variable;

    %local i quoted_word;
    %do i = 1 %to &SQLOBS;

      %let quoted_word = &&&sq_word&i;

      if (indexw(&newvar.,&quoted_word)) then 
        &newvar = tranwrd(&newvar,&quoted_word,'');

    %end;
  run;

%mend;

%flense();

【讨论】:

    【解决方案3】:

    您可以尝试使用哈希迭代器,例如:

    data want;
       if 0 then set STOPWORDS;
       if _n_=1 then do;
          declare hash h(dataset:'STOPWORDS');
          declare hiter iter('h');
          h.definekey('StopWords');
          h.definedata('StopWords');
          h.definedone();
       end;
       set ANNU_COMMENTS;
          rc=iter.first();
          do while(rc=0);
              newComment=ifc(findw(newComment,strip(StopWords))>0,tranwrd(newComment,strip(StopWords),''),newComment);
              rc=iter.next();
          end;
        drop StopWords rc;
    run;
    

    【讨论】:

      【解决方案4】:

      基本思路是replace():

      SELECT REPLACE(t1.Comment, 'jumped', '')
      FROM BOW.ANNU_COMMENTS t1;
      

      但是,您遇到了空格问题。如果这是一个问题并且您想要完整的单词,那么这可能会起作用:

      SELECT TRIM(BOTH ' ' FROM REPLACE(' ' || t1.Comment || ' ', ' jumped ', ''))
      FROM BOW.ANNU_COMMENTS t1;
      

      【讨论】:

      • 我需要使用表中的所有单词 SELECT t1.StopWords FROM BOW.STOPWORDS 而不仅仅是单词“jumped”
      猜你喜欢
      • 2018-09-28
      • 2016-01-21
      • 1970-01-01
      • 2021-12-29
      • 2020-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-21
      相关资源
      最近更新 更多