使用indsname计算变量频率

时间:2015-07-03 01:50:52

标签: sas

我在多个数据集中有一个公共列ID。现在,我正在寻找在这些数据集中出现多少次ID。即使ID在一个数据集中多次出现,数据集中的visit仍会计为1

对于任何mID数据集给定visit,值1介于mID # Visit 222 5 233 5 556 3 ... ... 667 1 之间。

理想输出:

222

数据集:(它们没有相同的前缀,这是一个例子)。

data1 :( ID col2 col3 ... 21 222 222 的#访问次数为1,即使出现两次)

222

...

data5 :( ID col87 col12 ... 222 623 126 的#访问次数为1)

tau:
A | B | C
----------    
2 - 1 - 12351
3 - 1 - 65462
4 - 1 - 13461
6 - 5 - 12351
7 - 5 - 12351
8 - 5 - 62372
9 - 10 -12351

我不知道如何从这开始。它看起来像是一本字典遍历。

3 个答案:

答案 0 :(得分:4)

这没有经过测试,但沿线应该有效:

/*Stack up all of your tables, keep 'ID' only*/
data have (keep=ID);
set data: indsname=dsn;
dsname = dsn;
run;

/*Proc SQL to get the job done*/
Proc sql;
create table want as
select ID, count(distinct dsname) as visit from have
group by ID
;
quit;

答案 1 :(得分:0)

这是一个数据步骤方法,假设所有数据集都按ID排序。

基本上,您将当前行的indsname值与前一行进行比较,如果更改,则将计数增加1.注意与重置计数的方法略有不同 - 我在之后执行 em> indsname检查,并且为1,之前不为0;那是因为在某些情况下,您可能有两个具有不同indsname值的连续ID。由于我们不能在BY语句中使用INDSNAME,因此我们不能依赖SAS来“改变”我们的值(就像我们使用嵌套的语句一样)所以我们必须不按顺序执行。

data data1;
  do id = 1 to 20;
    output;
  end;
run;

data data2;
  do id = 1 to 30 by 2;
    output;
  end;
run;

data data3;
  do id = 1 to 30 by 3;
    output;
  end;
run;

data want;
  set data: indsname=dsn;
  by id;
  count+ifn(dsn=lag(dsn),0,1);
  if first.id then count=1;
  if last.id then output;
run;

答案 2 :(得分:0)

我认为以下解决方案会起作用(您必须提供要在其上计算统计信息的数据集的列表):

%macro macro_answer(dataset_list);
%let ndsets = %sysfunc(countw(&dataset_list., ' '));

/* Create a frequency table for every dataset in the list of input datasets, containing a column with the dataset name */
/* and the count of each ID in this dataset */
%do i = 1 %to &ndsets;
    proc sql;
        create table __freq_&i. as
        select "%scan(&dataset_list., ' ')" as dataset_name
                ,ID
                ,count(*) as _count_
        from %scan(&dataset_list., ' ')
        group by 1,2
    ;quit;
%end;

/* Append every frequency table create above */
data __all_datasets_freq;
    length dataset_name $41.; /*8 for libname + 1 for '.' + 32 for dataset name*/
    set 
        %do i = 1 %to &ndsets;
            __freq_&i.;
        %end;
run;

/* Drop intermediary tables for frequency of each dataset */
proc sql;
        %do i = 1 %to &ndsets.;
            drop table __freq_&i.;
        %end;
;quit;
%mend macro_answer;

Haikuo Bian提供的解决方案可能有效,并且也更易于理解,但以我的经验,您应该始终对数据集计算统计信息,然后堆叠所有表,而不是堆叠所有表并计算统计信息。大桌子根据您的计算机和表的大小,使用前者可以提高性能。

此外,如果您的表位于数据库(Teradata,Oracle等)上,并且您正在使用SAS Pass-Through,则无需使用即可通过最有效的方式使用数据库Pass-Through SAS在计算统计信息之前附加所有表并在大表上创建。除此之外,对我的代码进行少量调整,您就可以使用字典表 dictionary.tables 在具有特定模式名称的数据集上遍历整个lib(甚至在lib列表上)。

免责声明:我现在无法访问SAS,因此无法确认我提供的代码是否确实有效。