#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();