根据其他几个列创建半累积列。 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
.
您不需要 col2
和 col1
- first.col3
是您关心的,其他两个更改也会导致 first.col3
也为真默认。
你也不希望那里有 First.date
- 每次日期更改时 first.date
都是真的(或 by
中它之前的任何其他变量),并且发生在每一行,所以它 总是 正确!你不想要那个。
最后,您需要为 flag
创建一个新变量。旧变量实际上 总是 保留!但它们也会在每次迭代中被替换为新值。所以我们将它重命名为 flag_early
或任何你喜欢的名称,并使用 max
函数将 1 分配给 flag
任何时候 flag_early 有一个 1 或者 保留标志中的 1(如果它以前有)- 每次 first.col3
为真时再次重置它。
我得到了一些数据,这些数据本质上是很多 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
.
您不需要 col2
和 col1
- first.col3
是您关心的,其他两个更改也会导致 first.col3
也为真默认。
你也不希望那里有 First.date
- 每次日期更改时 first.date
都是真的(或 by
中它之前的任何其他变量),并且发生在每一行,所以它 总是 正确!你不想要那个。
最后,您需要为 flag
创建一个新变量。旧变量实际上 总是 保留!但它们也会在每次迭代中被替换为新值。所以我们将它重命名为 flag_early
或任何你喜欢的名称,并使用 max
函数将 1 分配给 flag
任何时候 flag_early 有一个 1 或者 保留标志中的 1(如果它以前有)- 每次 first.col3
为真时再次重置它。