1

我正在尝试获取某个变量列表的模式。当模式不是唯一的时,我想返回模式的平均值,以便获取模式的子查询(在更大的查询中)不返回两个值。但是,当模式是唯一的时,由于某种原因,平均查询会返回一个缺失值。

我有以下示例数据:

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;

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

感谢您对此的任何帮助。

4

3 回答 3

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;

这不会花很长时间,对另一个程序员来说你在做什么更清楚,并且很容易编码。如果您不采用模式的平均值,则可以一步完成。

于 2013-08-22T14:00:43.180 回答
2

首先,请注意,您在外部查询中没有 group by 语句,而您确实使用了 having 子句。这是不行的。

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

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. 在过滤器中使用聚合函数。
您不能在存在 group by 语句的情况下执行第一个,而在没有 group by 语句的情况下无法执行第二个。

因此,最终结果是,我将第一个保留在外部查询中,同时在附加子查询中执行第二个。

于 2013-08-22T12:56:03.803 回答
1

这非常困难,在与 SAS 合作 12 年后,我不记得我曾经/见过在没有 GROUP BY 的情况下使用 HAVING,我想它会产生意想不到的结果。

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

单个查询版本:

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;

请注意,您可以通过 PROC MEANS 计算 MODE 和 MEDIAN 等统计数据:

proc means data=have n mean mode median;
var betprice;
run;
于 2013-08-22T12:57:56.613 回答