暂停数据并仅选择一些分段值

时间:2018-06-09 22:09:01

标签: sas

假设我希望仅校准数据值,其中每个类别中的值的频率大于或等于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类,将在(频率= 11,14)上校准值-0.9和-0.5。不同的类别将分别进行校准。 我正在尝试使用SAS只选择每个类别中频率大于或等于10的值。

最好先尝试选择一个值,然后再将其扩展到其余值。如果我将上面的数据集称为“已分类”,而我正在尝试创建“已校准”的新数据集,那么我的目标就是:

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

但是这只会生成一个名为“new”的额外列,其中“Categorized”数据集中值为-1的频率条目相同。我该怎么办?

2 个答案:

答案 0 :(得分:0)

你可以使用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;

答案 1 :(得分:0)

您尚未在输出中指出(a)所有原始记录的频率汇总是否满足您的条件,或者(b)只有符合条件的唯一(类别,值)对。

如果你想要(a),Kiran已经提供的SQL解决方案很好,是我能想到的最简洁的解决方案。但是,你想要它在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 ; 

如果你想要(b),即只有不同的(类别,值)对,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 ;          

此致

保罗多夫曼