Пакетирование данных и выбор только некоторых значений - PullRequest
0 голосов
/ 10 июня 2018

Скажем, я хочу выполнить калибровку только по значениям данных, где в каждой категории значения имеют частоту, большую или равную 10. (Это упрощение того, как данные, которые я имею, представлены в моей таблице SAS, естьпричина, по которой одно и то же значение для одной и той же категории появляется в разных строках, в фактическом наборе данных имеется 4 категории и сотни тысяч наблюдений значений )

  Category        Value                Frequency
  A             -1                       6
  A             -1                       7
  A             -0.5                     4
  A              0.1                     12
  B             -1                       9
  B             -0.9                     6
  B             -0.9                     5
  B             -0.5                     14

Так что вВ приведенном выше примере для категории A значения -1 и 0,1 будут откалиброваны, поскольку они имеют частоту 13 и 12 соответственно, что больше или равно 10, а -0,5 - нет.Однако для категории B значения -0,9 и -0,5 будут откалиброваны (частота = 11,14).Различные категории должны быть откалиброваны по отдельности.Я пытаюсь использовать SAS для выбора только значений, частота которых в каждой категории больше или равна 10.

Вероятно, лучше начать с попытки выбрать одно значение, прежде чем оно может быть расширено доостальное.Если я назову вышеупомянутый набор данных «Категоризованный», а новый, который я пытаюсь создать, «Калиброванный», я получу следующее:

data Calibrated;
     set Categorised;
     if Category="A" and Value= -1 then new = sum(Frequency);
run;

Но это просто создает дополнительный столбец с именем «новый» сте же самые записи для частоты для значения -1 в наборе данных «по категориям».Как мне поступить?

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Вы не указали, хотите ли вы (а) все исходные записи, чья совокупность частот удовлетворяет вашему условию, или (б) только уникальные пары (категория, значение), для которых выполняется условие.

Если вы хотите (а), решение SQL, уже предложенное Kiran, является хорошим и является самым кратким решением, которое я могу придумать.Однако, если вы хотите сделать это на шаге DATA, это также может быть сделано.Во-первых, давайте предположим, что ваши данные отсортированы по (категории, значению), как кажется.Затем вы можете закодировать так называемый двойной цикл DoW:

data want (drop = _:) ;               
  do _n_ = 1 by 1 until (last.value) ;
    set have ;                        
    by category value ;               
    _fsum = sum (_fsum, frequency) ;  
  end ;                               
  do _n_ = 1 to _n_ ;                 
    set have ;                        
    if _fsum > 10 then output ;       
  end ;                               
run ;                                 

Если ваши данные не отсортированы, для достижения эффекта можно использовать хеш-таблицу:

data want (drop = _:) ;                      
  dcl hash h (ordered:"a") ;                 
  h.definekey ("category", "value") ;        
  h.definedata ("_fsum") ;                   
  h.definedone () ;                          
  do until (last) ;                          
    set have end = last ;                    
    if h.find() ne 0 then _fsum = frequency ;
    else _fsum + frequency ;                 
    h.replace() ;                            
  end ;                                      
  do until (0) ;                             
    set have ;                               
    h.find() ;                               
    if _fsum > 10 then output ;              
  end ;                                      
run ; 

ЕслиВы хотите (б), т.е. только отдельные пары (категория, значение), SQL (в предложенной форме) не будет работать.Шаг DATA будет выполнен, если вы уменьшите код для решения для отсортированных входных данных до следующего:

data want (keep = category value) ;   
  do until (last.value) ;
    set have ;                        
    by category value ;               
    _fsum = sum (_fsum, frequency) ;  
  end ;                               
  if _fsum > 10 ;                     
run ;   

И для несортированных данных (подход хэширования):

data _null_ ;                                       
  dcl hash h (ordered:"a") ;                        
  h.definekey ("category", "value") ;               
  h.definedata ("category", "value", "_fsum") ;     
  h.definedone () ;                                 
  do until (last) ;                                 
    set have end = last ;                           
    if h.find() ne 0 then _fsum = frequency ;       
    else _fsum + frequency ;                        
    h.replace() ;                                   
  end ;                                             
  h.output (dataset:"want (where = (_fsum > 10))") ;
  stop ;                                            
run ;          

С уважением,

Пол Дорфман

0 голосов
/ 10 июня 2018

вы можете сделать что-то вроде ниже, используя proc sql.

data have;
input 
Category $       Value                Frequency;
datalines;
A             -1                       6
A             -1                       7
A             -0.5                     4
A              0.1                     12
B             -1                       9
B             -0.9                     6
B             -0.9                     5
B             -0.5                     14
;

proc sql;
create table have_to_calibrate as
select * from have
group by category, value
having sum(frequency)> 10;
...