保留以替换丢失数据的sas问题

保留以替换丢失数据的sas问题,sas,Sas,以下继承的简化代码旨在用组中不缺少项的值替换列中缺少的值: DATA WORK.TOYDATA; INPUT Category $ PRICE; DATALINES; Cat1 2 Cat1 . Cat1 . Cat2 . Cat2 3 Cat2 . ; DATA WORK.OUTTOYDATA; SET WORK.TOYDATA; BY Category ; RETAIN _PRICE; IF FIRST.Category THEN _PRICE=PRICE;

以下继承的简化代码旨在用组中不缺少项的值替换列中缺少的值:

DATA WORK.TOYDATA;
   INPUT Category $ PRICE;
   DATALINES;
Cat1 2
Cat1 .
Cat1 .
Cat2 .
Cat2 3
Cat2 .
;

DATA WORK.OUTTOYDATA;
SET WORK.TOYDATA;
   BY Category ;
   RETAIN _PRICE;
   IF FIRST.Category THEN _PRICE=PRICE;
   IF NOT MISSING(PRICE) THEN _PRICE=PRICE;
 ELSE PRICE=_PRICE;
 DROP _PRICE;
RUN;

不幸的是,如果组中的第一个条目丢失,这将不起作用。这怎么能解决呢

当SAS在数据集中逐行工作时,如果缺少第一个值,则没有可替换的值。 您可以按类别和降价对数据进行排序,以避免这种情况

proc sort data= WORK.TOYDATA; by Category DESCENDING PRICE; run; 
或者,如果类别中只有一个非缺失值,则可以使用sql联接,例如

proc sql;
create table WORK.OUTTOYDATA as
    select a.Category, coalesce(a.PRICE, b.PRICE) as PRICE
        from WORK.TOYDATA a
            left join   (select distinct Category, PRICE
                            from WORK.TOYDATA 
                                where PRICE ne .
                                ) b
            on a.Category eq b.Category
        ;
quit;

由于SAS在数据集中逐行工作,如果缺少第一个值,则没有可替换的值。 您可以按类别和降价对数据进行排序,以避免这种情况

proc sort data= WORK.TOYDATA; by Category DESCENDING PRICE; run; 
或者,如果类别中只有一个非缺失值,则可以使用sql联接,例如

proc sql;
create table WORK.OUTTOYDATA as
    select a.Category, coalesce(a.PRICE, b.PRICE) as PRICE
        from WORK.TOYDATA a
            left join   (select distinct Category, PRICE
                            from WORK.TOYDATA 
                                where PRICE ne .
                                ) b
            on a.Category eq b.Category
        ;
quit;

正如@Jetzler所指出的,最简单的方法就是对数据进行排序。但是,如果您有多个缺少值的列,那么您需要进行多个排序,这是没有效率的

执行联接的另一个选项是
proc stdize
,它可以用来用简单的度量(平均值、中值、总和等)替换缺少的值。在您的示例中,默认方法就足够了,您只需要添加
reponly
选项,该选项只替换缺少的值,而不标准化数据

DATA WORK.TOYDATA;
   INPUT Category $ PRICE;
   DATALINES;
Cat1 2
Cat1 .
Cat1 .
Cat2 .
Cat2 3
Cat2 .
;
run;

proc stdize data=TOYDATA out=want reponly;
by category;
var price;
run;

正如@Jetzler所指出的,最简单的方法就是对数据进行排序。但是,如果您有多个缺少值的列,那么您需要进行多个排序,这是没有效率的

执行联接的另一个选项是
proc stdize
,它可以用来用简单的度量(平均值、中值、总和等)替换缺少的值。在您的示例中,默认方法就足够了,您只需要添加
reponly
选项,该选项只替换缺少的值,而不标准化数据

DATA WORK.TOYDATA;
   INPUT Category $ PRICE;
   DATALINES;
Cat1 2
Cat1 .
Cat1 .
Cat2 .
Cat2 3
Cat2 .
;
run;

proc stdize data=TOYDATA out=want reponly;
by category;
var price;
run;

一个类别可以与几个不同的价格相关联,还是只与一个价格相关联?@Vincent-我认为可以,这是我看到的另一个问题……如果是这样,你需要一个规则来决定你要使用哪个值进行插补(例如最大值/最小值、你遇到的第一个值、随机存在的值等)。Jetzler回答将使用最大值,而Keith's将在每个类别中使用平均值。@vincent-谢谢。只是好奇是什么让Jetzler的答案明确地使用了最大值而不是最小值?一个类别可以与几个不同的价格相关联,还是只与一个价格相关联?@Vincent-我认为可以,这是我看到的另一个问题……如果是这样,你需要一个规则来决定要使用哪个值进行插补(例如最大值/最小值、遇到的第一个值、随机存在的值等)Jetzler的答案将使用最大值,而Keith的答案将使用每个类别的平均值。@vincent-谢谢。只是好奇Jetzler的答案为什么明确使用最大值而不是最小值?