|
|
楼主

楼主 |
发表于 2010-10-22 13:32:22
|
只看该作者
都是小数点惹的祸
From sxlion's blog on Sohu
<div style="FONT-SIZE: 14px; LINE-HEIGHT: 160%">
<p> 今天mymas上有人用了两种方法通过分组求平均数问题,发现结果不一样。为了说明问题,我自己简单地造了些数据,如下:</p>
<p> data dup;<br />input id date field value ;<br />cards;<br />1 2 0.0001 10<br />1 2 0.0001 10<br />1 2 0.00001 10<br />1 2 0.00001000001 10<br />1 3 0.00001 10<br />1 3 0.00001 10<br />1 3 0.00003 10<br />1 3 0.00003 10<br />1 3 0.00003 10<br />;<br />run;<br />proc sql; </p>
<p> create table NoDup1 as<br /> select unique id, date, field, avg(value) as value from Dup group by id, date, field; <br /> quit; ;<br />*method 2;<br />proc means data = Dup nway ;<br /> class id date field;<br /> var value;<br /> output out = NoDup2(drop = _type_ _freq_) mean = value;<br />run; <br />初一看来,好像代码没什么问题,应该结果一致,然而结果运行后,用sql得到的结果与proc步不一样,这是为什么? 似乎这是SAS的错误,哈哈这个多么伟大的一个发现啊! <img alt="大笑" src="http://js3.pp.sohu.com.cn/ppp/images/emotion/base/spit.gif" /> SAS可以说是总多行业里面的标准,竟然也会错。 <img alt="强" src="http://js3.pp.sohu.com.cn/ppp/images/emotion/base/strong.gif" /> <img alt="酷" src="http://js3.pp.sohu.com.cn/ppp/images/emotion/base/cool2.gif" /> <img alt="赞" src="http://js3.pp.sohu.com.cn/ppp/images/emotion/base/good.gif" /> 其实这不是第一次发现这类问题。<img alt="微笑" src="http://js3.pp.sohu.com.cn/ppp/images/emotion/base/smile.gif" /> 以前也遇到过同样的一个问题,就是:</p>
<p> data ex;<br /> do i= 0.05 to 0.15 by 0.01;<br /> if i=0.1 then output;<br /> end;<br /> run;</p>
<p> 这个代码运行后,ex数据集是空的,是不是SAS出错了。后来发现这是由于计算机存储小数的浮点问题,循环5次后,i应该等于0.1,实际上非常接近0.1,是个近似值,并不是等于0.1,因此并无数据输出到ex里面。</p>
<p> 那么回到上面的那个问题,根本原因是proc sql和proc mean步对数的小数点处理不同,proc mean考虑到小数点多于sql, 因此会导致nodup1比nodup2少一条观察。下面我提供第三种解决此类问题的代码,data步,也是商业大型数据的常用方法:</p>
<p> data nodup3;<br /> set dup;<br /> by id date field;<br /> if first.field then do; num=0;mean=0;end;<br /> num+1; mean+value;<br /> if last.field then do; value=mean/num; drop num mean; output; end;<br />run;</p>
<p>这个也是和proc mean步结果是一样的。</p>
<p>有时候也许不需要考虑没必要的小数位,可以用函数round,int,ceil等,还有一种方法就是把需要分组和比较大小的非整数用format格式化一下。</p>
<p> 一般来说,我如果发现SAS运行结果和我想的不一样,可以归结于两点:1,自己的代码有问题;2,小数点问题。</p></div> |
|