我正在尝试为人员和时间的每个唯一组合对与代码列值匹配的值列值求和。这个概念应该很简单,但我似乎无法管理......:
INPUT TABLE:
Time | Person | Value| Code
_____________________________________
1 | A | 10 | Z1
1 | A | 11 | Z2
1 | A | 12 | Z3
1 | A | 13 | Z4
1 | A | 20 | Z5
2 | A | 23 | Z1
2 | A | 21 | Z2
2 | A | 33 | Z3
2 | A | 32 | Z4
2 | A | 37 | Z5
1 | B | 38 | Z1
1 | B | 43 | Z2
1 | B | 12 | Z3
1 | B | 13 | Z4
1 | B | 10 | Z5
2 | B | 10 | Z1
2 | B | 11 | Z2
2 | B | 22 | Z3
2 | B | 23 | Z4
2 | B | 10 | Z5
等..................更多的人,时间和代码。
我想对code-column
= Z1
和Z3
的值列求和。对于Code
= Z2
,Z4
和Z5
等每个人,每次都没有代码中的结构我总结。
所以输出会是这样的:
Time | Person | NewValue| NewCode
_____________________________________
1 | A | 22 | "Z1+Z3"
1 | A | 43 | "Z2+Z4+Z5"
1 | B | 50 | "Z1+Z3"
1 | B | 66 | "Z2+Z4+Z5"
2 | A | 56 | "Z1+Z3"
2 | A | 90 | "Z2+Z4+Z5"
2 | B | 32 | "Z1+Z3"
2 | B | 44 | "Z2+Z4+Z5"
等..................
我希望这个概念很清楚 - 我希望根据代码列对每个独特的人 - 时组合进行求和。我想要总结的代码没有逻辑。 (Z2+Z4
,或Z10+Z11+Z12+Z17
和Z16+Z20
等代码也可以多次使用。我只是有一个手动不断变化的列表,其中包含要汇总的代码。)< / p>
到目前为止,我尝试了很多方法,例如:
PROC SQL;
CREATE TABLE output AS
SELECT value FROM input
WHERE code = "Z1" + value WHERE code = "Z3"
AND time=time AND person=person;
QUIT;
虽然这是语法乱码,但它确实说明了我正在尝试的内容。
答案 0 :(得分:0)
由于您总是手动创建新值,因此您可以在外部文件中保留要求总和的列表。
File: Combination.xlsx
Combination
Z1 Z2 Z3
Z1 Z4
Z2 Z5
...
接下来,创建一个程序,读取这些组合并将它们保存到宏变量中。您可以使用SQL过滤每个组合。
proc import file='C:\Location\Combination.xlsx'
out=_Import_Combination
dbms=xlsx
replace;
run;
下面将创建一个新变量,将您的组合转换为IN()
语句的正确语法。例如"Z1","Z3","Z5"
data Combination;
set _Import_Combination;
do i = 1 to countw(Combination);
if(i = 1) then Filter = quote(scan(Combination, i) );
else Filter = catt(Filter, ",", quote(scan(Combination, i) ) );
end;
run;
接下来,将组合名称和过滤器保存到宏变量中。
proc sql noprint;
select Combination
, Filter
, count(*)
into :combos separated by '|',
:filter separated by '|',
:total_combos
from Combination
;
quit;
最后,循环遍历您需要的所有组合。您可以使用SQL过滤每个组合。
%macro countAllCombos;
%do i = 1 %to &total_combos;
%let current_combo = %scan(&combos, &i, |);
%let current_filter = %scan(%bquote(&filter), &i, |);
proc sql noprint;
create table %sysfunc(tranwrd(¤t_combo, %bquote( ), _) ) as
select Time
, Person
, NewCode
, sum(Value) as Total_Value
from input
where code IN(¤t_filter)
group by Time, Person
;
quit;
%end;
%mend;
%countAllCombos;
最终输出将是存储在名为:
的WORK库中的表Z1_Z2_Z3
Z1_Z4
Z2_Z5
...
答案 1 :(得分:0)
找到解决方案。最简单,最快捷的方法是首先将INPUT表转换为“按人员和时间进行分组分析”,使用“代码”作为“新列名”,将值作为“转置变量”。
接下来,您可以使用以下内容来总结您想要的w / e代码:
%_eg_conditional_dropds(WORK.OUTPUT);
PROC SQL;
CREATE TABLE WORK.OUTPUT(label="OUTPUTname") AS
SELECT t1.Person,
t1.Time,
(SUM(t1.'Column Z1'n,t1.'Column Z3'n)) AS 'NewCode 1'n,
(SUM(t1.'Column Z2'n,t1.'Column Z4'n,t1.'Column Z5'n)) AS 'NewCode2'n
QUIT;
这甚至可以通过使用算术而不是“sum”命令来扩展和简化,例如:
/*Instead of*/
(SUM(t1.'Column Z1'n,t1.'Column Z3'n)) AS 'NewCode 1'n,
/*do stuff like:*/
t1.'Column Z1'n + t1.'Column Z3'n - (t1.'Column Z3'n - t1.'Column Z5'n) AS 'NewCode 1'n,
/*etc.*/