Удаление дубликатов ответов, содержащих специальные символы, в опросе - PullRequest
0 голосов
/ 26 мая 2018

Здравствуйте, я имею дело со следующей проблемой.У меня есть опрос, в котором вы смогли отметить несколько ответов, а также добавить свой собственный.Я пытаюсь получить уникальные ответы, чтобы иметь возможность подсчитать их возникновение, например: предположим, что у нас есть 3 ответа: a, b, c.Лицо № 1 помечено ответом a, Лицо № 2 помечено ответом b, c, Лицо № 3 помечено ответом a, c.Я хотел бы получить результат: «а» был отмечен 2 раза.Для этого я пытаюсь удалить дубликаты ответов и создать макропеременную, в которой хранятся эти уникальные ответы: a, b, c.

Я уже переименовал все вопросы опроса в v1-v & n_que.где n_que - это макропеременная, в которой хранится информация о количестве вопросов в опросе.Я пытался разбить все ответы на таблицы (в предыдущем примере я получил столбец со следующими значениями): a, b, c, a, c.Затем я хотел отсортировать эти данные и удалить дубликаты.Я пробовал следующее:

%macro coll_ans(lib, tab);
    %do _i_ = 1 %to &n_que. %by 1;
            %global betav&_i_.;

            proc sql noprint;
                    select distinct v&_i_. into :betav&_i_. separated by ', '
                            from &lib..&tab.
                                where v&_i_. ^= ' ';
            quit;

            data a&_i_.;
                %do _j_ = 1 %to %sysfunc(countw(%quote(&&&betav&_i_.), ',')) %by 1;
                    text = %scan(%quote(&&&betav&_i_), &_j_., ',');
                    output;
                %end;
            run;
    %end;
%mend coll_ans;

Стоит отметить, что если кто-то выбрал более 1 ответа, например, a и b, ответы разделяются запятой, поэтому я выбрал этот разделитель, чтобыунифицировать запись.Я перепробовал почти все, изменив% quote на% bquote,% superq, написав && вместо &&&, и я продолжаю получать следующую ошибку (сначала из 40 других):

 ERROR: The function NO is unknown, or cannot be accessed.

«НЕТ» - это одно изответ на первый вопрос в опросе, полный ответ: НЕТ (переходите к 9-му вопросу).Стоит отметить, что весь опрос сделан на польском языке, но я использую правильную кодировку, поэтому я не верю, что это может вызвать некоторые проблемы (надеюсь).

Я буду благодарен за все советы, потому что я столкнулсянепреодолимая стена

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Прежде всего, было бы лучше, если бы вы опубликовали формат, в котором вы получаете данные опроса, поскольку это будет диктовать самый простой / быстрый подход в целом.

Кроме того, как правило, лучше всего правильно настроить входы и выходы в немакрос-коде SAS, а затем использовать макросы для оптимизации процесса и т. Д. Так проще отлаживать - даже для тех, кто используетмакросы в течение длительного времени ...:)

Тем не менее, из вашего кода Proc SQL видно, что:

a.вы получаете ответы в одном текстовом поле с разделителями, например, «a, b, c» или «b, c» или «a, b, z»

*** example data;
data work.answers;
    length answer $10.;
    input answer;
    datalines;
    a,b,c
    a
    b
    b,c
    NO
    a,b,z
    n
run;

*** example valid answer entries;
data work.valid;
    length valid $10.;
    input valid;
    datalines;
    a
    b
    c
    NO
    YES
run;

b.Вы хотите проверить каждую запись ответа и сгенерировать счетчики, например:

NO  1   
YES 0   
a   3   
b   4   
c   2   

Многие способы сделать это в SAS, но для разбора токенизированных текстовых данных удобна дедуплицированная таблица поиска с использованием объекта хеша.Приведенный ниже код также выводит в журнал следующее для отладки / проверки ...

answer=a,b,c num_answers=3 val=a val=b val=c validated=a,b,c
answer=a num_answers=1 val=a validated=a
answer=b num_answers=1 val=b validated=b
answer=b,c num_answers=2 val=b val=c validated=b,c
answer=NO num_answers=1 val=NO validated=NO
answer=a,b,z num_answers=3 val=a val=b val=z -invalid validated=a,b, validated=a,b,
answer=n num_answers=1 val=n -invalid validated=  validated= 

После того, как вы освоили синтаксис объявления для хеш-объекта, это довольно логично и относительно быстро.И, конечно, вы можете добавить правила проверки - такие как прописные и строчные записи ...

*** first, de-duplicate your lookup table. ;
proc sort data=work.valid nodupkey;
by valid;
run;

data _null_;
    length valid $10. answer_count 4. count 4. validated $10.;
    retain count 0;

    *** initialize & load hash object ;
    if _N_ = 1 then do;

        declare hash h(multidata: 'n', ordered: 'y');
        rc = h.defineKey('valid');
        rc = h.defineData('valid','count');
        rc = h.defineDone();        

        do until(eof1);
            set work.valid end=eof1;
            h.add();
        end;

    end;

    *** now process questions/answers;
    do until(eof);

        *** read each answer;       
        set answers end=eof;        
        num_answers=countw(answer);
        putlog answer= num_answers= @;

        *** parse each answer entry;
        validated=answer;
        do i=1 to num_answers;

            val=scan(answer,i);
            putlog val= @;

            *** (optional) keep track of total #answers: valid + invalid;
            answer_count+1;

            *** check answer entry in lookup table;
            rc= h.find(key:val);

            *** if entry NOT in lookup table, remove from validated answer;
            if rc ne 0 then do;
                putlog "-invalid " @;
                validated=tranwrd(validated,trim(val),' ');
            end;

            *** if answer found, increment counter in lookup table;
            else do;
                count+1;
                h.replace();
            end;

        end;    
        putlog validated=;

    end;

    *** save table of answer counts to disk;
    if eof then h.output(dataset: 'work.counts');

run;
0 голосов
/ 27 мая 2018

Предполагается, что у вас есть набор данных, например:

data have ;
  input id v1 : $8. v2 : $8.;
  cards ;
  1 a   a
  2 b,c b
  3 a,c c
;

Вы можете транспонировать набор данных, чтобы он имел одну запись на каждое значение переменной ID.

data tran (keep=id VarName Value);
  set have ;
  array vars{*} v1 v2 ;
  do i=1 to dim(vars) ;
    Varname=vname(vars{i}) ;
    do j=1 to countw(vars{i},',') ;  
      Value=scan(vars{i},j,',') ;
      output ;
    end ;
  end ;
run ;

Выходной набор данных выглядит следующим образом:

id    Varname    Value

 1      v1         a
 1      v2         a
 2      v1         b
 2      v1         c
 2      v2         b
 3      v1         a
 3      v1         c
 3      v2         c

Вы можете использовать PROC FREQ или SQL для получения значений.

proc freq data=tran ;
  tables varname*value/missing list ;
run ;

Выходы

Varname    Value    Frequency
v1         a               2
v1         b               1
v1         c               2
v2         a               1
v2         b               1
v2         c               1
...