Sas 如何使用数组对变量进行水平排序并使用call sortc
sasprofessionals.net上的一位用户遇到了一个问题,即无法通过几个变量对其数据集进行分组,因为变量值在观察中是可互换的,因为它们具有相同的含义 在示例数据集中,观测值2、3和7是相同的,因为它们每个都有A14、A14和A10作为Stat1到Stat3的值,只是顺序不同。这些应按计数分组。观察结果5和6构成另一组,应通过计数进行总结 示例数据集:Sas 如何使用数组对变量进行水平排序并使用call sortc,sas,Sas,sasprofessionals.net上的一位用户遇到了一个问题,即无法通过几个变量对其数据集进行分组,因为变量值在观察中是可互换的,因为它们具有相同的含义 在示例数据集中,观测值2、3和7是相同的,因为它们每个都有A14、A14和A10作为Stat1到Stat3的值,只是顺序不同。这些应按计数分组。观察结果5和6构成另一组,应通过计数进行总结 示例数据集: Obs Stat1 Stat2 Stat3 Count 1 A14 A14 A14 53090 2 A14 A1
Obs Stat1 Stat2 Stat3 Count
1 A14 A14 A14 53090
2 A14 A14 A10 6744
3 A14 A10 A14 5916
4 A01 A01 A01 4222
5 A10 A10 A10 3085
6 A10 A10 A10 2731
7 A10 A14 A14 2399
理想产出:
Obs Stat1 Stat2 Stat3 Count
1 A14 A14 A14 53090
4 A01 A01 A01 4222
6 A10 A10 A10 5816
7 A10 A14 A14 15059
实际数据集更大、更复杂。我不知道用户是否尝试了任何方法来解决问题
这个问题最初发布在sasportials.net上,为了社区的利益,它被复制到了StackOverflow。它被更改为符合StackOverflow Q&A标准。这是我解决用户问题的答案。通常,我将Stat1-Stat3加载到一个数组中,使用sortc调用函数对数组进行排序,然后用一个临时ID对其进行汇总,该临时ID由排序后的Stat1-Stat3数组构造而成
/* Loading the data into SAS dataset */
/* Loading Stat1-Stat3 into an array */
/* Sorting stat1-stat3 creating a new ID */
data have;
input obs stat1 $ stat2 $ stat3 $ count;
array stat{3} stat1-stat3;
call sortc(of stat1-stat3);
ID = CATX("/",stat1,stat2,stat3);
datalines;
1 A14 A14 A14 53090
2 A14 A14 A10 6744
3 A14 A10 A14 5916
4 A01 A01 A01 4222
5 A10 A10 A10 3085
6 A10 A10 A10 2731
7 A10 A14 A14 2399
;
/* sorting the data set in preparation for data step with by statement*/
PROC SORT data=have;
BY ID OBS;
RUN;
/* Summarising the dataset and outputing into final dataset*/
DATA summed (drop=ID count);
set sorted_arrays;
by ID;
retain sum 0;
if first.ID then sum = 0;
sum + count;
if last.ID then output;
RUN;
/* Sorting it back into original order */
PROC SORT data=summed out=want;
BY OBS;
RUN;
因为我一直在给自己做散列练习,所以我决定通过散列来尝试。Paul Dorfman有几篇论文讨论了如何使用哈希表对数组进行排序,例如 下面,我使用一个哈希表进行水平排序,然后使用另一个哈希表按ID对计数进行求和。数据只需读取一次,但考虑到数据的大小,在这种情况下,我肯定不会要求效率优势。我没有将数据返回到原始排序顺序 欢迎编辑/提问/建议,因为这是我哈希学习曲线的一部分。:)
Vasilij,虽然我认为像这样交叉发布信息是个好主意,但你现在的问题应该是一个好的堆栈溢出问题。将数据粘贴为图片在任何地方都是不允许的,而且问题通常也应该包含代码——而不仅仅是“为我这样做”。一般来说,我认为如果你想做这样的事情,应该是更“基本”的概念;这确实是一个非常具体的解决方案,在其他情况下没有多大帮助。自我回答的问题最好是你想告诉别人的东西,因为很多人都有相同的问题。如果您想展示
sortc
的好处,一个更简单的问题可能会更好-简单地用一个更简单的示例“如何按变量的值排序”会更好。这涉及太多的其他代码,这将使它难以理解。嘿,乔,公正的评论。下次我会记住这一点。在这个特定的案例中,我只是简单地用最少的编辑交叉发布了问题和答案,因为我认为这对一些用户来说是有益的,而不需要投入大量时间编辑或直接更改。我理解,但它本身仍然必须对StackOverflow有效。对不起,您从“好的堆栈溢出问题”到“对堆栈溢出有效”。是哪一个?我的问题有效还是不是很简单,但仍然可以?:)
data have;
input stat1 $ stat2 $ stat3 $ count;
datalines;
A14 A14 A14 53090
A14 A14 A10 6744
A14 A10 A14 5916
A01 A01 A01 4222
A10 A10 A10 3085
A10 A10 A10 2731
A10 A14 A14 2399
;
data want;
length _stat $3;
if _n_=1 then do;
declare hash hstat(multidata:"y", ordered:"y");
declare hiter hstatiter ("hstat" ) ;
hstat.definekey('_stat');
hstat.definedata('_stat');
hstat.definedone();
call missing(_stat);
declare hash hsum(suminc: "count", ordered: "y");
declare hiter hsumiter ("hsum" ) ;
hsum.definekey("stat1","stat2","stat3");
hsum.definedone();
end;
set have end=last;
array stat{3};
*load the array values into htable hstat to sort them;
*then iterate over the hash, returning the values to array in sorted order;
do _i=1 to dim(stat);
hstat.add(key:stat{_i},data:stat{_i});
end;
do _i=1 to dim(stat);
hstatiter.next();
stat{_i}=_stat;
end;
_rc=hstatiter.next(); *hack- there is no next, this releases hiter lock so can clear hstat;
hstat.clear();
*now that the stat keys have been sorted, can use them as key in hash table hsum;
*as data are loaded into/checked against the hash table, counts are summed;
*Then if last, iterate over hsum writing it to output dataset;
hsum.ref(); *This sums count as records are loaded/checked;
if last then do;
_rc = hsumiter.next();
do while(_rc = 0);
_rc = hsum.sum(sum: count);
output ;
_rc = hsumiter.next();
end;
end;
drop _: ;
run;