2016-07-11 4 views
0

Я хотел бы присвоить идентификаторы с пустыми размерами, основанными на частотном распределении их группы.Присвоить отсутствующие значения переменных на основе распределения SAS

Dataset А содержит снимок моих данных:

ID Group Size 
1 A  Large 
2 B  Small 
3 C  Small 
5 D  Medium 
6 C  Large 
7 B  Medium 
8 B  - 

Dataset B показывает частотное распределение размеров среди групп:

Group Small Medium Large 
A  0.31 0.25 0.44 
B  0.43 0.22 0.35 
C  0.10 0.13 0.78 
D  0.29 0.27 0.44 

Для ID 8, мы знаем, что он имеет 43% вероятность быть «малой», 22% вероятность быть «средним» и 35% вероятность быть «большой». Это потому, что это дистрибутивы по размеру для группы B.

Как присвоить идентификатор 8 (и другие пустые идентификаторы) размер, основанный на распределении групп в наборе данных B? Я использую SAS 9.4. Макросы, SQL, все приветствуется!

ответ

0

Плата table идеально подходит для этого. Последний пример показывает это; перед этим я настраивал вещи для произвольного создания данных и определял частотную таблицу, поэтому вы можете пропустить это, если вы уже это сделали.

См. Блог Рика Уиклина о simulating multinomial data для примера этого в других случаях использования (и дополнительной информации о функции).

*Setting this up to help generate random data; 
proc format; 
    value sizef 
    low - 1.3 = 'Small' 
    1.3 <-<2.3 = 'Medium' 
    2.3 - high = 'Large' 
; 
quit; 

*Generating random data; 
data have; 
    call streaminit(7); 
    do id = 1 to 1e5; 
    group = byte(65+rand('Uniform')*4); *A = 65, B = 66, etc.; 
    size = put((rank(group)-66)*0.5 + rand('Uniform')*3,sizef.); *Intentionally making size somewhat linked to group to allow for differences in the frequency; 
    if rand('Uniform') < 0.05 then call missing(size); *A separate call to set missingness; 
    output; 
    end; 
run; 

proc sort data=have; 
    by group; 
run; 

title "Initial frequency of size by group"; 
proc freq data=have; 
    by group; 
    tables size/list out=freq_size; 
run; 
title; 

*Transpose to one row per group, needed for table distribution; 
proc transpose data=freq_size out=table_size prefix=pct_; 
    var percent; 
    id size; 
    by group; 
run; 


data want; 
    merge have table_size; 
    by group; 
    array pcts pct_:; *convenience array; 

    if first.group then do _i = 1 to dim(pcts); *must divide by 100 but only once!; 
    pcts[_i] = pcts[_i]/100; 
    end; 

    if missing(size) then do; 
    size_new = rand('table',of pcts[*]); *table uses the pcts[] array to tell SAS the table of probabilities; 
    size = scan(vname(pcts[size_new]),2,'_'); 
    end; 
run; 



title "Final frequency of size by group"; 
proc freq data=want; 
    by group; 
    tables size/list; 
run; 
title; 
+0

Это сработало! Спасибо за вашу помощь. – user3910919

0

Вы также можете сделать это с помощью случайной величины, а некоторые, если-то еще логика:

proc sql; 
    create table temp_assigned as select 
     a.*, rand("Uniform") as random_roll, /*generate a random number from 0 to 1*/ 
     case when missing(size) then 
      case when calculated random_roll < small then small 
       when calculated random_roll < sum(small, medium) then medium 
       when calculated random_roll < sum(small, medium, large) then large 
      end end as value_selected, /*pick the value of the size associated with that value in each group*/ 
     coalesce(case when calculated value_selected = small then "Small" 
        when calculated value_selected = medium then "Medium" 
        when calculated value_selected = large then "Large" end, size) as group_assigned /*pick the value associated with that size*/ 
     from temp as a 
     left join freqs as b 
     on a.group = b.group; 
quit; 

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

Смежные вопросы