Удаление слов из поля с помощью слов из таблицы в SAS

#sql #sas

#sql #sas

Вопрос:

Я пытаюсь удалить слова из поля в 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;
  

Комментарии:

1. на всякий случай, если вы ищете динамическую замену. sqlservercentral.com/forums/topic /…

Ответ №1:

В зависимости от того, сколько слов у вас есть другие решения.

 data _NULL_;
    set STOPWORDS end=e;
    if _N_=1 then call execute('data resu<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;
  

Для этого потребуются стоп-слова, из которых будет генерироваться datastep, а не комментарии к этому процессу обработки данных.

РЕДАКТИРОВАТЬ: чтобы удалить только слова по границе слова, вы должны использовать b в регулярном выражении.

 data _NULL_;
    set STOPWORDS end=e;
    if _N_=1 then call execute('data resu<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;
  

Комментарии:

1. Привет, Ли, как я могу заставить это сгенерировать новое поле без каких-либо стоп-слов и поместить его рядом с полем комментария как «новый комментарий»

2. Сначала просто скопируйте новую переменную, а затем измените ее. Я отредактировал код, чтобы отразить это.

3. Я получаю следующую ошибку: 582 если _N_=1, то __000000000000000000000000000291 prxparse(«s / HERSE»//»);» __ 388 76 ОШИБКА 388-185: ожидание арифметического оператора. ОШИБКА 76-322: синтаксическая ошибка, оператор будет проигнорирован.

4. ПРИМЕЧАНИЕ: Система SAS прекратила обработку этого шага из-за ошибок. ПРЕДУПРЕЖДЕНИЕ: набор данных РАБОТАЕТ. РЕЗУЛЬТАТ может быть неполным. Когда этот шаг был остановлен, было 0 наблюдений и 25 переменных. ПРЕДУПРЕЖДЕНИЕ: набор данных РАБОТАЕТ. РЕЗУЛЬТАТ не был заменен, поскольку этот шаг был остановлен.

5. Это потому, что ваше слово имеет » внутри

Ответ №2:

Основная идея заключается в replace() :

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

Однако у вас проблема с пробелами. Если это проблема и вам нужны полные слова, то это может сработать:

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

Комментарии:

1. Мне нужно использовать все слова в таблице SELECT t1.StopWords ИЗ BOW.STOPWORDS, а не только слова «прыгнул»

Ответ №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:

Можно написать макрос, который генерирует этап очистки данных.

В этом примере использование tranwrd от Shenglin сочетается с codegen от Lee.

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

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

  data amp;out;
    set amp;data;
    amp;newvar = amp;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 amp;SQLOBS;

      %let quoted_word = amp;amp;amp;sq_wordamp;i;

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

    %end;
  run;

%mend;

%flense();