SAS中是否有一种优雅的方法可以在不使用一系列sql语句的情况下在多个级别上计算“计数不同”?
假设我们正在计算唯一客户。 Joe已购买了2个大窗口部件和1个小窗口部件,这很简单,就可以将他算作1个大窗口部件的客户和1个小窗口部件的客户。但是我们还需要将他视为仅1个“小部件客户”,因此需要单独的SQL计算。事实证明,乔还购买了一个鼠标垫,因此当我们为“杂项产品”组计算唯一客户时,我们需要进行第三次SQL计算。乔从#1商店购买了所有这些东西,但是当我们计算“小商店编号区域”的杂项产品的唯一客户时,我们还必须考虑到Joe从#2商店购买的咖啡杯。另一个SQL计算。
SAS中有很多计算事物的方法,但是似乎没有简单的方法可以计算“不同”的事物。有什么建议么?
最佳答案
您在这里遇到了一些不同的问题,这取决于数据的结构。遗憾的是您没有提供,所以我决定!
我们将假设您有一个这样的数据集。您还可以在两行中购买两次LargeWidget(对于其他产品也是如此),对此没有任何影响。
data customers;
length product $20;
input name $ product $ store $ count;
datalines;
Joe SmallWidget Store1 1
Joe LargeWidget Store1 2
Joe Mousepad Store1 1
Joe TeaPitcher Store2 1
Jack SmallWidget Store2 1
Jack Mousepad Store1 1
Jane LargeWidget Store2 1
Jane Mousepad Store1 1
Jill LargeWidget Store3 1
;;;;
run;
然后,我们需要进行另一项设置:确定打算如何对事物进行分组。多标签格式允许您要求一个值落入多个存储桶(即,大型小部件和所有小部件)。这是一个例子,您可以在这里做很多不同的事情。您也可以从数据集中进行此操作(在proc格式中查找
CNTLIN
选项,或询问其他问题)。proc format;
value $prodgroup (multilabel default=20)
SmallWidget = "Small Widgets"
SmallWidget = Widgets
LargeWidget = "Large Widgets"
LargeWidget = Widgets
Mousepad = Mousepads
Mousepad = "Misc Products"
TeaPitcher = "Tea Pitchers"
TeaPitcher = "Misc Products"
;
value $storeRegions (multilabel)
Store1=Store1
Store1=West
Store2=Store2
Store2=East
Store3=Store3
Store3=East
;
quit;
然后,我们面临一个大问题:SAS在计算“不同”的事物上很费力。这样做并不是真正做到的。我不知道为什么;制表确实应该,但事实并非如此。但是,将它们放在桶中确实做得很好,这确实是这里的难点。实际的唯一计数位可以在第二遍中完成(不管您的初始数据大小如何,这都会非常快,前提是您假设产品的种类少于数据点的种类)。
proc tabulate data=customers out=custdata;
class product store /mlf preloadfmt order=data;
class name;
format product $prodgroup20.;
format store $storeRegions6.;
tables (all store product store*product),name*n;
run;
proc tabulate data=custdata;
class product store/missing;
tables (product*store), n;
run;
MLF PRELOADFMT ORDER=DATA
使multilabel位正常工作,并使其以有用的顺序出现(我认为)。您可以在NOTSORTED
的value语句中添加PROC FORMAT
以获得更多控制权,尽管第二个PROC TABULATE
只会按顺序弄乱事情,因此我不会打扰。在这种情况下,我们要做的是首先生成一个由客户创建的表,然后将该表输出到数据集;现在,只要在两个proc中都对分组进行了镜像(当然要减去NAME类!),就可以保证该数据集每个[无论分组]每位客户都包含一行。
此过程的一个不足之处是,它不会为那些具有0的产品生成行,而不必为您提供第二行列表,而是在SQL或数据步骤中执行。例如:
proc tabulate data=customers out=custdata2;
class product store /mlf preloadfmt order=data;
class name;
format product $prodgroup20.;
format store $storeRegions6.;
tables (all store product store*product),name*n/printmiss;
run;
proc sql;
select product, store, sum(case when n>0 then 1 else 0 end) as count
from custdata2
group by product,store;
quit;
请注意对TABLE行的一项更改:
printmiss
,它指示Tabulate对任何可能的组合都使用一行。然后SQL
完成其余工作。当然,如果您喜欢SQL,此SQL也可以更早地复制第二个Tabulate语句。
关于sql - SAS:如何在多个级别上计算不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27421565/