根据其他几个列创建半累积列。 SAS

Create semi-cumulative columns based off several other columns. SAS

我得到了一些数据,这些数据本质上是很多 information/data 和日期的列,然后是两列数字和一个标志列(即它是 1 或 0)。每行都是关于某个人在特定月份的信息。

对于两列数字,我想创建两个新列,它们是每个人随时间的累积数字。对于标志,我希望它在该人的所有未来日期都为 1,一旦它首先成为该人的 1。

我很难说出这个(google 我想做什么!)所以我把我拥有的和我想要的放在下面。在这个例子中:A1、B1、C1 是一个人,A1、B2、C3 是另一个人。

我知道了:

Col1 Col2 Col3 Date Value_1 Value_2 Flag
A1 B1 C1 01Jan2021 0 100 0
A1 B1 C1 01Feb2021 0 0 0
A1 B1 C1 01Mar2021 10 100 0
A1 B1 C1 01Apr2021 50 0 0
A1 B1 C1 01May2021 0 10 1
A1 B1 C1 01Jun2021 10 0 0
A1 B1 C1 01Jul2021 0 0 0
A1 B2 C3 01Jan2021 0 0 0
A1 B2 C3 01Feb2021 0 20 1
A1 B2 C3 01Mar2021 10 20 0
A1 B2 C3 01Apr2021 40 20 0
A1 B2 C3 01May2021 0 0 0
A1 B2 C3 01Jun2021 30 0 0
A1 B2 C3 01Jul2021 0 0 0

我想要这个:

Col1 Col2 Col3 Date Value_1_full Value_2_full Flag
A1 B1 C1 01Jan2021 0 100 0
A1 B1 C1 01Feb2021 0 100 0
A1 B1 C1 01Mar2021 10 200 0
A1 B1 C1 01Apr2021 60 200 0
A1 B1 C1 01May2021 60 210 1
A1 B1 C1 01Jun2021 70 210 1
A1 B1 C1 01Jul2021 70 210 1
A1 B2 C3 01Jan2021 0 0 0
A1 B2 C3 01Feb2021 0 20 1
A1 B2 C3 01Mar2021 10 40 1
A1 B2 C3 01Apr2021 50 60 1
A1 B2 C3 01May2021 50 60 1
A1 B2 C3 01Jun2021 80 60 1
A1 B2 C3 01Jul2021 80 60 1

如果我只有一个人的数据,我可以做到这一点,但有很多人。我写的代码只是给了我列的总累计值——我不知道如何为每个人分别计算它们。出于类似的原因,我也在努力编写标志列的代码。我已将代码放在下面,非常感谢任何 help/advice.

注意:我真的是 SAS 的新手,为了写这个问题,我一直在努力通过为这个例子输入数据来正确地输入日期字段(我使用了这个“忽略”位下面的代码作为将其导入 SAS 的变通方法)所以如果你能让我知道我在这里做错了什么,那我将来也会非常感激!

data data_1;
input Col1 $ Col2 $ Col3 $ Date date8. Ignore Value_1 Value_2 Flag;
format Date date8.;
datalines;
A1 B1 C1 "'01Jan2021'd" 0 100 0
A1 B1 C1 "'01Feb2021'd" 0 0 0
A1 B1 C1 "'01Mar2021'd" 10 100 0
A1 B1 C1 "'01Apr2021'd" 50 0 0
A1 B1 C1 "'01May2021'd" 0 10 1
A1 B1 C1 "'01Jun2021'd" 10 0 0
A1 B1 C1 "'01Jul2021'd" 0 0 0
A1 B2 C3 "'01Jan2021'd" 0 0 0
A1 B2 C3 "'01Feb2021'd" 0 20 1
A1 B2 C3 "'01Mar2021'd" 10 20 0
A1 B2 C3 "'01Apr2021'd" 40 20 0
A1 B2 C3 "'01May2021'd" 0 0 0 
A1 B2 C3 "'01Jun2021'd" 30 0 0
A1 B2 C3 "'01Jul2021'd" 0 0 0
;
run;

Data data_2;
set data_1;
drop Ignore;
run;


proc sort data=data_2
    out=data_3;
    by Col1 Col2 Col3 Date;
run;


data data_4;
    set data_3;
    by Col1 Col2 Col3 Date;
 
    retain Col1 Col2 Col3 Date Value_1 Value_2 Flag Value_1_full Value_2_full;
 
    if first.Col1 AND first.Col2 AND first.Col3 AND first.Date then Value_1_full = Value_1;
    else Value_1_full = Value_1_full + Value_1;
run;

所以你非常接近!我想这就到了......

proc sort data=data_1(drop=ignore)
    out=data_3;
    by Col1 Col2 Col3 Date;
run;


data data_4;
    set data_3;
    by Col1 Col2 Col3 Date;
 
    retain Col1 Col2 Col3 Date Value_1 Value_2 Flag Value_1_full Value_2_full;
 
    if first.Col3 then Value_1_full = Value_1;
    else Value_1_full = Value_1_full + Value_1;


    if first.col3 then flag=0;
    flag = max(flag,flag_Early);

run;

只有一些小改动。我删除了一个无意义的数据步骤(drop 可以在您使用数据的任何其他地方完成)并将 if first. 更改为 if first.col3.

您不需要 col2col1 - first.col3 是您关心的,其他两个更改也会导致 first.col3 也为真默认。

你也不希望那里有 First.date - 每次日期更改时 first.date 都是真的(或 by 中它之前的任何其他变量),并且发生在每一行,所以它 总是 正确!你不想要那个。

最后,您需要为 flag 创建一个新变量。旧变量实际上 总是 保留!但它们也会在每次迭代中被替换为新值。所以我们将它重命名为 flag_early 或任何你喜欢的名称,并使用 max 函数将 1 分配给 flag 任何时候 flag_early 有一个 1 或者 保留标志中的 1(如果它以前有)- 每次 first.col3 为真时再次重置它。