2016-07-11 11 views
0

Ich möchte IDs mit leeren Größen eine Größe basierend auf der Häufigkeitsverteilung ihrer Gruppe zuweisen.Fehlende Variablenwerte basierend auf Verteilung zuweisen SAS

Datensatz A enthält eine Momentaufnahme meiner Daten:

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

Datensatz B zeigt die Häufigkeitsverteilung der Größen unter den Gruppen:

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 

Für ID 8, wissen wir, dass es eine hat 43% Wahrscheinlichkeit, "klein" zu sein, 22% Wahrscheinlichkeit "mittel" und 35% Wahrscheinlichkeit "groß" zu sein. Das liegt daran, dass dies die Größenverteilungen für Gruppe B sind.

Wie weise ich ID 8 (und anderen leeren IDs) eine Größe zu, die auf den Gruppenverteilungen in Datensatz B basiert? Ich benutze SAS 9.4. Makros, SQL, alles ist willkommen!

Antwort

0

Die table Verteilung ist ideal dafür. Der letzte Datenblock hier zeigt das; zuvor habe ich Dinge eingerichtet, um die Daten nach dem Zufallsprinzip zu erstellen und die Häufigkeitstabelle zu bestimmen, so dass Sie das überspringen können, wenn Sie das bereits tun.

Siehe Rick Wicklins Blog über simulating multinomial data für ein Beispiel in anderen Anwendungsfällen (und weitere Informationen über die Funktion).

*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

Das hat funktioniert! Danke für Ihre Hilfe. – user3910919

0

Sie können auch mit einem zufälligen Wert und einige if-else-Logik dies tun:

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; 

Natürlich können Sie dies tun, ohne die value_selected Variable zu schaffen, aber ich dachte, es zu Demonstrationszwecken zeigen würde sei hilfreich.

Verwandte Themen