2017-04-12 100 views
0

我想特别本月平均值来代替所有0.0如何用sas或sql中的组平均值替换0?

value date  month year 
33.2 01SEP2016 9 2016 
33.7 02SEP2016 9 2016 
34.8 03SEP2016 9 2016 
33.8 04SEP2016 9 2016 
33.7 05SEP2016 9 2016 
33.8 06SEP2016 9 2016 
32.7 07SEP2016 9 2016 
33.4 08SEP2016 9 2016 
32.5 09SEP2016 9 2016 
33.7 10SEP2016 9 2016 
32.7 11SEP2016 9 2016 
32.5 12SEP2016 9 2016 
32.1 13SEP2016 9 2016 
32.2 14SEP2016 9 2016 
32.0 15SEP2016 9 2016 
31.8 16SEP2016 9 2016 
31.8 17SEP2016 9 2016 
31.9 18SEP2016 9 2016 
32.5 19SEP2016 9 2016 
32.5 20SEP2016 9 2016 
32.3 21SEP2016 9 2016 
32.6 22SEP2016 9 2016 
14.2 23SEP2016 9 2016 
0.0  24SEP2016 9 2016 
0.0  25SEP2016 9 2016 
0.0  26SEP2016 9 2016 
0.0  27SEP2016 9 2016 
0.0  28SEP2016 9 2016 
0.0  29SEP2016 9 2016 
0.0  30SEP2016 9 2016 
+0

发现然后将其合并回原始表,如果值为0.0,则将其替换为平均值 – NEOmen

+0

并且还有另一种情况,我需要将av最后三次发生的情况。那么将会怎样处理?例如。我在“2016年9月24日”有0值,那么我需要平均23,22,21七月。 –

+0

接下来的几天如何? 27日,28日等,目前没有价值的前3天? – Longfish

回答

0

你的问题的第一部分是很容易的。首先将零值更改为缺失值,然后使用proc stdsize将缺失值更改为月份的平均值。

/* create initial dataset */ 
data have; 
input value date :date9. month year; 
format date date9.; 
datalines; 
33.2 01SEP2016 9 2016 
33.7 02SEP2016 9 2016 
34.8 03SEP2016 9 2016 
33.8 04SEP2016 9 2016 
33.7 05SEP2016 9 2016 
33.8 06SEP2016 9 2016 
32.7 07SEP2016 9 2016 
33.4 08SEP2016 9 2016 
32.5 09SEP2016 9 2016 
33.7 10SEP2016 9 2016 
32.7 11SEP2016 9 2016 
32.5 12SEP2016 9 2016 
32.1 13SEP2016 9 2016 
32.2 14SEP2016 9 2016 
32.0 15SEP2016 9 2016 
31.8 16SEP2016 9 2016 
31.8 17SEP2016 9 2016 
31.9 18SEP2016 9 2016 
32.5 19SEP2016 9 2016 
32.5 20SEP2016 9 2016 
32.3 21SEP2016 9 2016 
32.6 22SEP2016 9 2016 
14.2 23SEP2016 9 2016 
0.0  24SEP2016 9 2016 
0.0  25SEP2016 9 2016 
0.0  26SEP2016 9 2016 
0.0  27SEP2016 9 2016 
0.0  28SEP2016 9 2016 
0.0  29SEP2016 9 2016 
0.0  30SEP2016 9 2016 
; 
run; 

/* replace zeros with missing */ 
data have; 
modify have; 
call missing(value); 
where value=0; 
run; 

/* replace missing with mean of month */ 
proc stdize data=have out=want 
      method=mean reponly; 
by month year; 
var value; 
run; 
0

您可以使用proc sql生成一个新的结果集:

proc sql; 
    select (case when t.value = 0 then t2.avg_value else value end) as value, 
      t.date, t.month, t.year 
    from t left join 
     (select year, month, avg(value) as avg_value 
      from t 
      group by year, month 
     ) t2 
     on t.year = t2.year and t.month = t2.month; 

如果你想短语以此为update,然后我会用一个相关子查询:

proc sql; 
    update t 
     set value = (select avg(t2.value) 
        from t t2 
        where t2.value <> 0 and 
          t2.year = t.year and t2.month = t.month 
        ) 
     where value = 0; 
+0

我相信你需要给子查询添加一个where子句,以便它在平均值计算中不包括零(这个问题并不完全清楚,但是包含它们没有多大意义)。另外,由于您无法引用子查询 – Longfish

+0

@Longfish中正在更新的表,因此您的更新语句不起作用。 。 。我现在没有SAS现在正在测试。它真的有这个限制吗?据我所知,唯一有此限制的数据库是MySQL。 –

+0

是的!错误消息表示您无法重新打开更新访问表,因为它已被使用。这表明它首先运行子查询(这是有道理的),但保持表打开,因此阻止更新 – Longfish