luckycai 发表于 2012-9-14 20:46 
发现一个奇怪的问题,我调用了这一段程序,数据从2008开始的,2008Q1的std算出来居然是0,2008Q1一共一千多 ...
一开始理解有歧义,以为2008Q1季度,就是求第一个值的均值和标准差,所以均值永远是第一个值,标准差
没有计算,一直为初值0
改后的程序:
data ex;
input
date $ x;
cards;
2008Q1 1
2008Q1 1
2008Q2 2
2008Q2 2
2008Q3 3
2008Q4 4
2008Q4 3
2009Q1 2
2009Q2 1
2009Q3 3
2009Q3 2
;
run;
data ex1;
set ex;
year=input(scan(date,1,'Q'),4.);
q=input(scan(date,2,'Q'),1.);
run;
proc iml;
use ex1;
read all var{year q x} into g;
q=j(nrow(g),2,0);
/*给q矩阵赋初值为0,用来存储mean,std*/
do i=1 to nrow(g);
/*从矩阵第一行循环到最后一行*/
if i=1 then do;
/*如果是第一行*/
n=((g[,1]=g[i,1])&(g[,2]=g[i,2]))[+];
/*这里计算year=2008且Q=1的记录条数n*/
q[i,1]=g[1:n,3][:];
/*求前n行的均值作为2008Q1的均值*/
q[i,2]=((g[1:n,3]-g[1:n,3][:])##2)[:]##0.5;
/*这里其实是求前n行的std,iml中的std函数不是很好用,这里其实是按标准差公式算的,即每个记录减去均值,求平方和的均值,最后开根号*/
end;
else if all(g[i,1:2]=g[i-1,1:2]) then do;
/*如果不是第一行,且该行year的值等于上一行year的值,Q的值也相等,那该行的均值标准差为空值*/
q[i,1]=.;
q[i,2]=.;
end;
else do;
/*如果都不属于上述情况,即每年,每个季度的第一个值,就求它上面所有行的均值以及标准差*/
q[i,1]=g[1:i-1,3][:];
q[i,2]=((g[1:i-1,3]-g[1:i-1,3][:])##2)[:]##0.5;
/*之前的程序其实求的方差,这边添加##0.5,表示矩阵每个元素开0.5次方,即开根,也可以用sqrt函数,效果一样*/
end;
end;
create ans from q[colname={'mean','std'}]; /*将q矩阵导入到ans数据集中,列名称分别为mean 和 std*/
append from q;
quit;
data ans;
merge ex ans;
run;