2015-09-09 2 views
0

У меня есть набор данных в SAS, содержащий людей в виде строк и переменную для каждого периода в виде столбцов. Это выглядит примерно так:Число столбцов в SAS

data have; 
input individual t1 t2 t3; 
cards; 
1 112 111 123 
2 112 111 123 
3 111 111 123 
4 112 112 111 
; 
run; 

То, что я хочу для SAS, чтобы подсчитать, сколько существует каждого числа для каждого периода времени. Поэтому я хочу, чтобы получить что-то вроде этого:

data want; 
input count t1 t2 t3; 
cards; 
111 1 3 1 
112 3 1 0 
123 0 0 3 
; 
run; 

Я мог бы сделать это с помощью PROC FREQ, но выводя это не очень хорошо работает, когда у меня есть много столбцов.

Благодаря

ответ

2

В общем, имеющих данные в мета-данных, это плохая идея, так как здесь, где ПЕРИОДА кодируется в переменных Tn, и вы действительно хотите, чтобы быть группой. Сказав, что вы все еще можете иметь свой торт и съесть его тоже.

PROC SUMMARY может быстро получать счета для каждого Tn, а затем у вас будет меньший набор данных, с которым можно будет играть. Вот один из подходов, который должен хорошо работать в течение многих периодов времени.

data have; 
    input individual t1 t2 t3; 
    cards; 
1 112 111 123 
2 112 111 123 
3 111 111 123 
4 112 112 111 
;;;; 
run; 
proc print; 
    run; 
proc summary data=have chartype; 
    class t:; 
    ways 1; 
    output out=want; 
    run; 
proc print; 
    run; 
data want; 
    set want; 
    p = findc(_type_,'1'); 
    c = coalesce(of t1-t3); 
    run; 
proc print; 
    run; 
proc summary data=want nway completetypes; 
    class c p; 
    freq _freq_; 
    output out=final; 
    run; 
proc print; 
    run; 
proc transpose data=final out=morefinal(drop=_name_) prefix=t; 
    by c; 
    id p; 
    var _freq_; 
    run; 
proc print; 
    run; 

enter image description here

+0

\ _TYPE_ и \ _FREQ_ становится преобразованы в курсивные показатели по SO. Добавьте \ вперед. – Tom

+0

«В общем, данные в метаданных - плохая идея». Зачем? –

+0

Поскольку это затрудняет использование, как в этом примере, где период времени и значение (111 112) занимают одно и то же пространство. Если период времени был переменной, то он мог использоваться непосредственно в классе. Который я закончил делать во втором ПРОЦЕССЕ. –

0

Если ваш компьютер памяти достаточно велик, чтобы вместить весь выход, то Hash может быть жизнеспособным решением:

data have; 
    input individual t1 t2 t3; 
    cards; 
1 112 111 123 
2 112 111 123 
3 111 111 123 
4 112 112 111 
; 
run; 

data _null_; 
    if _n_=1 then 
     do; 
      /*This is to construct a Hash, where count is tracked and t1-t3 is maintained*/ 
      declare hash h(ordered:'a'); 
      h.definekey('count'); 
      h.definedata('count', 't1','t2','t3'); 
      h.definedone(); 
      call missing(count, t1,t2,t3); 
     end; 

    set have(rename=(t1-t3=_t1-_t3)) 
     /*rename to avoid conflict between input data and Hash object*/ 
    end=last; 

    array _t(*) _t:; 
    array t(*) t:; 

    /*The key is to set up two arrays, one is for input data, 
    another is for Hash feed, and maneuver their index variable accordingly*/ 
    do i=1 to dim(_t); 
     count=_t(i); 
     rc=h.find(); /*search the Hash and bring back data elements if found*/ 

     /*If there is a match, then corresponding 't' will increase by '1'*/ 
     if rc=0 then 
      t(i)+1; 
     else 
      do; 
       /*If there is no match, then corresponding 't' will be initialized as '1', 
            and all of the other 't' reset to '0'*/ 
       do j=1 to dim(t); 
        t(j)=0; 
       end; 

       t(i)=1; 
      end; 

     rc=h.replace(); /*Update the Hash*/ 
    end; 

    if last then 
     rc=h.output(dataset:'want'); 
run; 
1

Сначала реструктурировать данные таким образом, что он находится в более вертикальный мода. С этим будет легче работать. Мы также хотим создать флаг, который мы будем использовать в качестве счетчика позже.

data have2; 
    set have; 
    array arr[*] t1-t3; 

    flag = 1; 
    do period=lbound(arr) to hbound(arr);  
    val = arr[period]; 
    output; 
    end; 

    keep period val flag; 
run; 

Подведите итоги так, чтобы у нас было количество раз, которое произошло в каждом из периодов.

proc sql noprint; 
    create table smry as 
    select val, 
     period, 
     sum(flag) as count 
    from have3 
    group by 1,2 
    order by 1,2 
    ; 
quit; 

Транспонирование данные таким образом, мы имеем одну строку на значение, а затем отсчеты в течение каждого периода после этого:

proc transpose data=smry out=want(drop=_name_); 
    by val; 
    id period; 
    var count; 
run; 

Заметим, что при определении массива в первом шаге вы могли бы использовать эти обозначения который позволил бы для динамического ряда периодов:

array arr[*] t:; 

Это предполагает каждую переменную, начинающиеся с «т» в наборе данных должны идти в массив.

0

Попробуйте это:

%macro freq(dsn); 
proc sql; 
select name into:name separated by ' ' from dictionary.columns where libname='WORK' and memname='HAVE' and name like 't%'; 
quit; 
%let ncol=%sysfunc(countw(&name,%str())); 
%do i=1 %to &ncol; 
%let col=%scan(&name,&i); 
proc freq data=have; 
table &col/out=col_&i(keep=&col count rename=(&col=count count=&col)); 
run; 
%end; 
data temp; 
    merge 
    %do i=1 %to &ncol; 
     col_&i 
    %end; 
; 
by count; 
run; 
data want; 
    set temp; 
    array vars t:; 
    do over vars; 
    if missing(vars) then vars=0; 
    end; 
run; 
%mend; 

%freq(have)