如何为现有数据集创建一个新列,该数据集是现有列的运行总计 - 由某个标识符分区?
ID | Value | New Value
---|--------|--------------------
1 | 10 | 10
1 | 5 | 15 = 10 + 5
1 | 3 | 18 = 10 + 5 + 3
2 | 45 | 45
2 | 15 | 60 = 45 + 15
我习惯使用简单的SUM()OVER()语句在SQL(Oracle)中完成此操作,但PROC SQL中显然不支持该语法。
如果可能的话,我想在PROC SQL中实现这一点(我对SQL比SAS编码更有经验。)
谢谢!
麦克
答案 0 :(得分:4)
在数据步骤中,这是通过sum statement
完成的。
data want;
set have;
by id;
if first.id then running_total=0;
running_Total + value;
run;
在PROC SQL中,除非你有一个排序变量(你可以做这样的事情),否则这是不可能的:
proc sql;
create table want as
select id, value,
(select sum(value) from have V
where V.id=H.id and V.ordervar le H.ordervar
) as running_total
from have H
;
quit;
但SAS没有partition by
概念 - SAS数据步骤远比那更强大。
答案 1 :(得分:2)
我通常使用data
步而非proc sql
在SAS中运行总计。理论上你可以用proc sql
和交叉连接来做到这一点,但这在现实世界中并不是很实用。
第1步:按ID值对数据进行排序
proc sort data=have;
by ID;
run;
第2步:使用和语句计算运行总计
data want;
set have;
by ID;
New_Value+Value;
output;
if(last.ID) then New_Value = 0;
run;
<强>解释强>
分组处理是SAS最强大的工具之一。当您按ID值排序并在数据步骤中对其使用by-statement时,您将解锁两个新的特殊布尔变量:first.<by-group variable>
和last.<by-group variable>.
SAS确切知道何时启动一组ID变量,当你进行分组处理时停止(你实际上可以使用一个名为notsorted
的特殊选项来逃避而不对ID值进行排序,但这是一个高级概念)。在你的情况下,让我们来看看它是如何工作的:
ID Value first.ID last.ID
1 10 1 0
1 5 0 0
1 3 0 1
2 45 1 0
2 15 0 1
如果ID组中只有一个观察值,first.ID
和last.ID
都会为1。
SAS中有一个特殊的声明,称为sum语句,它既可以保留变量,也可以对变量求和。 SAS本质上是一种循环语言;每当它通过data
步骤时,它只查看一条记录和一条记录。当它到达data
步骤的底部并返回到顶部时,开始读取表中的下一条记录,并假设所有变量现在再次丢失,直到它读取或计算变量的值。你输出的东西是程序数据向量的内容。在后台,这就是你在操纵的东西。
默认情况下,只有在达到run
边界后才会输出到数据集。如果您明确告诉SAS输出,它只会在您告诉它时输出。为了累积一个变量,我们想告诉SAS四件事:
实现步骤1&amp; 2,你可以做两个选择:
data want;
set have;
retain New_Value;
New_Value = sum(New_Value, Value);
OR
data want;
set have;
New_Value+Value;
请注意,第二个选项与第一个选项完全相同,但工作量较少。把它想象成一条捷径。这称为Sum语句。看起来它在语法上是错误的,但它是一个特殊的,非常有用的案例。
要实现第3步,我们只是告诉SAS默认输出,而不是默认情况下在数据步骤结束时输出:
data want;
set have;
New_Value+Value;
output;
如果按原样运行上面的代码,New_Value
将无限期地加起来,直到它到达文件的最后。我们希望在到达新ID组后重置此值。我们使用by-group处理解锁这两个布尔变量,在输出后在指定条件下将New_Value
重置为0:
data want;
set have;
by ID;
New_Value+Value;
output;
if(last.ID) then New_Value = 0;
run;
New_Value
将不会重置为0,除非我们处于指定ID组的最后一次观察中。请注意,我们将条件if
语句放在输出语句下面。如果超过此值,您会看到以下现象:
ID Value New_Value first.ID last.ID
1 10 10 1 0
1 5 15 0 0
1 3 0 0 1
2 45 45 1 0
2 15 0 0 1
我们希望在 New_Value
重置为0之前输出累积和。
您可以使用其他一些SAS程序来执行类似的操作,但它们是针对特定情况设计的。在这种情况下,您可以重新调整它们以执行您想要的操作,但最好在跳转到程序重新调整之前学习data
步骤处理。
答案 2 :(得分:0)
这是另一种选择:
data want;
do until (last.id);
set have;
by id;
new_value + value;
output;
end;
new_value = 0;
run;
答案 3 :(得分:-1)
data want;
set have;
by id;
if first.id then running_total = 0;
if first.id then retained_total = 0;
running_total = retained_total + value;
retained_total = running_total;
retain retained_total;
run;