【问题标题】:return the most frequent value within columns返回列中出现频率最高的值
【发布时间】:2015-07-01 16:15:43
【问题描述】:

我在 SAS 中有一个表格,例如一个 customer_id 和 5 列,其中包含他的每月状态。客户有 6 种不同的状态。 例如

customer_id   month1    month2    month3    month4    month5 
12345678      Waiting   Inactive  Active    Active    Canceled

我想从最频繁的月份 1 - 月份 5 列中返回一个值。在这种情况下,它是值 Active。 所以结果将是

customer_id   frequent
12345678      Active    

SAS中有什么功能吗?我有一些想法如何使用 sql 来完成,但它会非常复杂,有很多案例条件等。我是 SAS 新手,所以我想会有一些更好的解决方案。

【问题讨论】:

  • SQL:反透视月份,按 customer_id 和月份分组,按 customer_id 分区,按 count desc 排序等。

标签: sql sas proc-sql


【解决方案1】:

如果您使用数组将数据集拆分为客户历史记录的每个月的一个观察值,您可以使用 proc sql 中的汇总函数轻松获取最频繁发生的事件并使用最近一个月(假设是第 5 个月)打破关系。

data want1;
    set have;
    array m(*) month1 -- month5;
    do i = 1 to dim(m);
        cid = customer_id;
        frequent = m(i);
        position = i;
        output;
    end;
    keep cid frequent position;
run;

proc sql;
    create table want2 as select
    cid as customer_id,
    frequent,
    max(position) as max_pos,
    count(frequent) as count
    from want1
    group by cid, frequent;
quit;

proc sort data = want2; by customer_id descending count descending max_pos; run;

data want3;
    set want2;
    by customer_id descending count descending max_pos;
    if first.customer_id;
    drop max_pos count;
run;

【讨论】:

    【解决方案2】:

    有点糟糕的解决方案,但它确实适用于 2 个不同的值,在本例中为 5 个月。如果活动数 >= 3,这是最常见的值:

    select customer_id, case when (case when month1 = 'Active' then 1 else 0 end +
                                   case when month2 = 'Active' then 1 else 0 end +
                                   case when month3 = 'Active' then 1 else 0 end +
                                   case when month4 = 'Active' then 1 else 0 end +
                                   case when month5 = 'Active' then 1 else 0 end) >= 3
                                 then 'Active' else 'Waiting' end
    from tablename
    

    另一种方式,UNION ALL

    select customer_id, month, count(*) as cnt
    (
        select customer_id, month1 as month from tablename
        UNION ALL
        select customer_id, month2 from tablename
        UNION ALL
        select customer_id, month3 from tablename
        UNION ALL
        select customer_id, month4 from tablename
        UNION ALL
        select customer_id, month5 from tablename
    )
    group by customer_id, month
    order by cnt
    fetch first 1 row only
    

    其中FETCH FIRST 是ANSI SQL,对于某些dbms 产品可能是TOPLIMIT

    【讨论】:

    • 谢谢。我有类似的想法。但问题是,可以有 6 个不同的值...
    • 也许您可以更新您的示例数据?如果是平局,你会期待什么结果?
    • 抱歉,你觉得领带怎么样?
    • 如果有 2 个 Active 和 2 个 Waiting(以及 1 个其他)。
    • 那么我想要最后一个(第 5 个月)。在每个值只有一次的情况下也是如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-16
    • 1970-01-01
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多