2013-08-22 143 views
1

我试图获取某个变量列表的模式。当模式不唯一时,我想返回模式的平均值,以便子查询获取模式(在较大的查询中)不返回两个值。但是,如果模式是唯一的,则由于某种原因,平均查询返回缺失值。SAS:单个观察的AVG()

我有下面的示例数据:

data have; 
input betprice; 
datalines; 
    1.05 
    1.05 
    1.05 
    6 
    run; 
    PROC PRINT; RUN; 

proc sql; 
select avg(betprice) 
    from 
    (select betprice, count(*) as count_betprice from have group by betprice) 
    having count_betprice = max(count_betprice); 
quit; 

如果我添加一些更多的观测到betprice场,这样的模式不是唯一的,我得到返回的平均值。

data have; 
input betprice; 
datalines; 
    1.05 
    1.05 
    1.05 
    6 
    6 
    6 

run; 
PROC PRINT; RUN; 

如何更改此查询,以便始终返回两个最常见值的模式或平均值。

感谢您的任何帮助。

+1

为什么你想要的平均模式?从统计角度来看,这根本不是一个有趣的术语。 MODE真正有用的唯一原因是看到分配。如果您采用均值模式,则MODE = 4不会告诉您是单项模式为4的二项分布,还是3和4和5全部相等的高原,或者实际上是1和7的偏斜。 – Joe

+0

我认为这很有趣!我想根据他们在前10次或20次投注中选择的投注分类进行分类。 Betprice不是一个连续变量,只有四个离散值:6,2,1.83和1.05。我如何根据他们的前10次投注对玩家进行排名?如果我取平均值,它不是很好,因为值6距离值1.05太远了。如果一名球员在1.05时有7次投注,在6次时有三次投注,我认为他应该被评为1.05。如果我拿平均水平,差不多是3:平均水平高于以2的价格进行10次投注的人。 – user2146441

+1

虽然我不认为模式本身的意思很有趣。如果它是一个平行线,那么你对它的处理取决于你的分析,但我不明白这个平均值是如何有用的?既然你有四个离散值,我想很明显他们的“模式均值”是一对特定对的平均值/模式,但是有人投注1.05和6的频率类似于频繁投注3.55的人(这是可能的)吗?看起来不像我。 – Joe

回答

1

这非常困难,在与SAS合作12年之后,我记不清使用HAVING而没有使用GROUP BY,我猜测它会产生意想不到的结果。

因此,对于单个查询,我的解决方案不是很好,因为它进行了两次分组。

一个查询版本:

proc sql; 
select avg(betprice) 
    from (select 
        betprice 
       , count(*) as count_betprice 
       from work.have 
       group by betprice) /* first summary */ 
    where count_betprice 
       = select max(count_betprice) 
     from 
      (select 
        betprice 
       , count(*) as count_betprice 
       from work.have 
       group by betprice) /* same summary here */; 
quit; 

使用中间表简化的位(或查看,如果你需要),而不是相同的子查询:

proc sql; 
create table work.freq_sum 
     as select 
       betprice 
       , count(*) as count_betprice 
       from work.have 
       group by betprice 
; 
select avg(betprice) 
    from work.freq_sum 
    where count_betprice 
       = select max(count_betprice) from work.freq_sum; 
quit; 

请注意,你可以计算统计像MODE和MEDIAN通过PROC MEANS:

proc means data=have n mean mode median; 
var betprice; 
run; 
+0

完整“有”表中的每一行都有一个时间戳,一个用户名,一个betprice和一些其他列。每个用户名有多个条目。较大的查询将提取每个用户名和玩家在1日至20日的平均betprice以及其他一些统计数据。您建议的第一个单一查询版本适用于此! – user2146441

+1

PROC UNIVARIATE更适合模式,因为它会返回多种模式。我也建议不要使用单个查询版本(因为vasja似乎也是这样),并不是因为它有什么问题,而是更容易阅读和维护第二个版本(尤其是如果您将第一部分视为一个视图)。写大复杂的查询并不代表良好的编程习惯,除非您正在尝试'工作安全性'。 – Joe

+0

因为我正在从一个赌桌上玩家名字,赌价,赌注金额等每一行,然后创建一个聚合表与每个球员独特的行,我不会立即看到分裂这个值进入一系列视图,中间数据包和临时表。使用'subselects'填充每个玩家行的列数据似乎更加简单。也许我在这方面走错了路。 。 – user2146441

2

首先,请注意,当您使用having子句时,外部查询中没有group by语句。哪个不好。

这里是一个有效的解决方案:

proc sql; 
    create view WORK.V_BETPRICE_FREQ as 
    select betprice, count(*) as count_betprice 
    from HAVE 
    group by betprice 
    ; 

    select avg(betprice) as final_betprice 
    from WORK.V_BETPRICE_FREQ 
    where count_betprice = (select max(count_betprice) from WORK.V_BETPRICE_FREQ) 
    ; 
quit; 

我用了一个观点在这里以防止代码重复。 如果在视图中的查询是一个非常繁重的CPU操作,您可能希望用物理表替换它。

编辑 反馈:我相信你,因为你想要的外部查询与查询挣扎:
1.过滤后在所有记录执行聚合功能。
2.在过滤器中使用聚合函数。
如果没有按语句提供语句,则无法在第二个语句中执行第一个语句,而您无法执行第二个语句。

因此最终的结果是,我在外部查询中保留了第一个,而在另一个子查询中执行了第二个查询。

3

你在SAS,为什么不让SAS计算吃了统计数据,因为这就是它的优点...

ods output modes=want; 
proc univariate data=have modes; 
var betprice; 
run; 
ods output close; 

proc means data=want; 
var mode; 
output out=final(keep=betprice) mean=betprice; 
run; 

这不会花太长的时间,对另一位程序员来说,你所做的事情要清楚得多,而且编码也很容易。如果你没有采取模式的意思,你可以一步到位。

+0

太好了,不知道UNIVARIATE可以产生多个MODE。比较选择较小的MEANS?? – vasja

+1

单变量和均值默认情况下选择最小的一个。如果您要求它(PROC UNIVARIATE语句中的模式选项),那么单变量也可以产生多种方式,但它必须与ODS OUTPUT一起输出,而不是输出语句。 – Joe