Sas 如何使用数组对变量进行水平排序并使用call sortc

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

sasprofessionals.net上的一位用户遇到了一个问题,即无法通过几个变量对其数据集进行分组,因为变量值在观察中是可互换的,因为它们具有相同的含义

在示例数据集中,观测值2、3和7是相同的,因为它们每个都有A14、A14和A10作为Stat1到Stat3的值,只是顺序不同。这些应按计数分组。观察结果5和6构成另一组,应通过计数进行总结

示例数据集:

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;