(我是SAS的新手,我很难理解按列进行操作的复杂程度,这在“正常”语言中是很容易的。如果这是非常基本的内容,请多多包涵。)>
我有一个表,其中包含值 type , a1-a10 和 b1-b10 ,我想查找(对于每个< em> N ) aN 为正的行的
proc sql;
create table work.test1 as
select type, b1
from work.table
where (a1 >0);
run;
,然后对所有这些表求和,然后合并它们,但这将是很多代码和一些麻烦。有没有一种不错且紧凑的方法来做到这一点?
编辑:我想要的输出是一个值为 type , sum1-sum10 的表,其中 sumN 是上述总和
样本数据:
type | a1 | a2 | ... | b1 | b2 | ...
------------------------------------
cat 10 14 ... 1 2 ...
cat -5 3 ... 1 1 ...
dog 35 -1 ... 9 3 ...
dog 9 2 ... 0.5 1 ...
所需的输出:
type | sum1 | sum2 | ...
------------------------
cat 1 3 ...
dog 9.5 1 ...
因此,对于每种 type 和 N ,求和那些 bN ,其中同一行的 aN 为正。
答案 0 :(得分:3)
这是一种proc summary
的方法。这并不像数组方法那样直接,但是将其归纳为您可能感兴趣的其他统计数据要容易得多。
data have;
input type $ a1 a2 b1 b2 ;
datalines;
cat 10 14 1 2
cat -5 3 1 1
dog 35 -1 9 3
dog 9 2 0.5 1
;
run;
/*Create a view of the dataset with suitable weight columns*/
data t_have / view = t_have;
set have;
array a[*] a1-a2;
do i = 1 to dim(a);
a[i] = a[i] > 0;
end;
run;
/*Use proc summary to sum across rows*/
proc summary nway data = t_have;
class type;
var b1 /weight=a1; /*You could macro-ise this bit to avoid excessive repetition*/
var b2 /weight=a2;
output out= want(drop=_:) sum= mean= /autoname;
run;
答案 1 :(得分:2)
您可以使用数组在单个步骤中以单个输出执行此任务。数组将值跨列存储在内存中,然后可以循环遍历以进行计算。
在此代码中,我创建了3个数组,一个数组用于A1-A2,一个数组用于B1-B2,一个数组用于新变量SUM1-Sum2。显然,在实际数据中,您可以将范围更改为A10,B10,SUM10。
我添加了很多注释来描述代码的作用,但是我还建议阅读数组以更好地理解。
/* create input data */
data have;
input type $ a1 a2 b1 b2;
datalines;
cat . 14 1 2
cat -5 3 1 1
dog 35 -1 9 3
dog 9 2 0.5 1
;
run;
/* sort data by type (needed for next step) */
proc sort data=have;
by type;
run;
data want;
set have;
by type; /* data neds to be sorted by this */
array var_a{2} a1-a2; /* store the values of a in an array */
array var_b{2} b1-b2; /* store the values of b in an array */
array sumvar{2} sum1-sum2; /* set up an array of sum variables (will also create physical variables) */
if first.type then do; /* set sum variables to zero when type changes */
do i = 1 to dim(sumvar);
sumvar{i} = 0;
end;
end;
do j=1 to dim(var_a); /* loop through each var_a value and add var_b to sum_N if var_a>0 */
if var_a{j}>0 then sumvar{j}+var_b{j}; /* syntax var1 + var2 retains value across rows */
end;
keep type sum: ; /* only keep required variables */
if last.type then output; /* only output last record for each type, with the total sum */
run;
答案 2 :(得分:2)
您可以在单个SQL
select
中为每个变量使用一个case
子句来完成此操作。
数据
data have; input
type $ a1 a2 b1 b2 ; datalines;
cat 10 14 1 2
cat -5 3 1 1
dog 35 -1 9 3
dog 9 2 0.5 1
run;
SQL示例
proc sql;
create table want_way1
as select
type
, sum (case when a1 > 0 then b1 else 0 end) as sum1
, sum (case when a2 > 0 then b2 else 0 end) as sum2
from have
group by type
;
SQL没有数组,因此将为每个 N a
和b
变量编写一个宏以生成整个SQL或仅生成所需的子句对。如果您希望宏发现 N 本身,则宏可以检查数据的元数据。
数据步骤示例
使用DOW循环进行组处理,并使用数组进行项目处理。如果删除注释,则非常紧凑。
data want_way2 (keep=type sum:);
do until (last.type);
set have;
by type;
* array statement is non-executable, but associates PDV variables with the array reference;
* array statement will create new variables in PDV if needed;
array a a1-a2; /* connects existing variables with array */
array b b1-b2; /* connects existing variables with array */
array s sum1-sum2; /* creates new variables and connects them with array */
* repurpose _n_ as simply an automatic variable that does not need to be dropped;
do _n_ = 1 to dim(a);
s(_n_) = sum ( s(_n_) , ifn ( a(_n_) > 0, b(_n_), 0 ) );
end;
end;
run;
答案 3 :(得分:1)
如果我了解您想要的内容,那么我认为将代码放在宏中可以解决问题。例如,在下面的示例中,我使用一个%do
循环来生成10个不同的数据集,每个N
一个。我所做的只是将您的代码包装在一个宏中,因此我希望您的代码能够满足您的要求。然后我用run
替换了您的quit
,否则proc sql
不会停止。
编辑:
options symbolgen mprint mlogic;
%macro Y(N=);
%macro compute;
%do i = 1 %to &N.;
proc sql;
create table work.test&i. as
select type, sum(b&i.) as sum&i.
from work.table
where (a&i. >0)
group by type
order by type;
quit;
%end;
%mend;
%compute;
data want;
%do i = 1 %to &N.;
merge test&i.;
%end;
run;
%mend;
%Y(N=10);