我有一个使用SAS创建计数变量的问题。
Q R
----
1 a
1 a
1 b
1 b
1 b
2 a
3 a
3 c
4 c
4 c
4 c
我需要创建一个变量S来计算具有相同Q和R组合的行。以下是输出。
Q R S
-------------------
1 a 1
1 a 2
1 b 1
1 b 2
1 b 3*
2 a 1
3 a 1
3 c 1
4 b 1
4 b 2
4 b 3
我尝试使用以下程序:
数据二;
设置一个;
S + 1;
由Q R;
如果是first.Q和first.R那么S = 1;
运行;
但是,这没有正常运行。例如,*将显示为1而不是3.我将不胜感激如何使这个计数变量正常工作。
答案 0 :(得分:3)
非常接近,你的if语句应该是first.R(或者改为和OR但是效率不高)。我通常喜欢在设置为1之后增加。
data two;
set one;
by Q R;
*Retain S; *implicitly retained by using the +1 notation;
if first.R then S = 1;
else S+1;
run;
答案 1 :(得分:1)
data two;
set one;
by Q R;
if first.R then s=0;
s+1;
run;
一旦first.Q
被移除,这可能与Reese的代码和原始问题的代码完全相同。但是,它有两点不同。
首先,我希望尽可能早地在一个地方将if first.
变量重置代码(不是取决于位置)分组(在语句之后,其中,& #34;早期"子集化if,array,format,length和retain)。这在组织的立场上是有用的,因为这个代码(通常)与SAS在数据步骤迭代之间的作用大致相同,但是对于BY组 - 所以在数据步骤开始时使用它是很好的。
其次,我喜欢初始化为零。这避免了else
条件的需要,这使得代码更清晰;除了重新初始化之外,你在每个BY组的第一行没有做任何不同的事情,所以没有增量是有条件的。
这些对于此数据步骤的更复杂版本都很有用;显然,在这一特定步骤中它并不重要,但在更大的数据步骤中,更有效地组织代码会很有帮助。想象一下这个数据步骤:
data two;
set one;
by Q R;
retain Z;
format Z $12.;
array CS[15];
if first.R then do; *re-init block;
S=0;
Z=' ';
end;
S+1; *increment counter;
do _t = 1 to dim(CS);
Z = cats(Z,ifc(CS[_t]>0,put(CS[_t],8.),''));
end;
keep Q R S Z;
run;
该数据步骤组织良好,并且具有逻辑流程,即使几乎每个步骤都可以移动到数据步骤中的任何其他位置。将初始化分组在一起使其更具可读性,特别是如果您总是以这种方式对事物进行分组。