如何根据SAS / SQL中的行值进行条件计数?

时间:2017-04-07 14:28:02

标签: sql excel sas

重新上传,因为我的上一篇文章存在一些问题,而且我不知道我们应该发布样本数据。我对SAS很新,我有一个问题,我知道如何在Excel中解决,而不是SAS。但是,数据集太大而无法在Excel中合理使用。

我有四个变量:id,year_start,groupname,test_score。

示例数据:

id     year_start     group_name     test_score
1       19931231          Red            90
1       19941230          Red            89
1       19951231          Red            91
1       19961231          Red            92
2       19930630          Red            85
2       19940629          Red            87
2       19950630          Red            95
3       19950931          Blue           90
3       19960931          Blue           90
4       19930331          Red            95
4       19940331          Red            97
4       19950330          Red            98
4       19960331          Red            95
5       19931231          Red            96
5       19941231          Red            97

我的目标是每年通过test_score获得排名列表(小数)。我希望能够使用PROC RANK FRACTION实现这一目标。此函数将通过test_score计算顺序(最高为1,第二高为2,依此类推),然后除以观察总数以提供小数等级。不幸的是,year_start在行与行之间存在很大差异。对于每个id / year组合,我想从年开始执行一年的回顾,并将该观察与所有其他在该一年范围内具有year_start的id进行排名。我对按日历年比较不感兴趣,每个id的等级应该相对于它自己的year_start。添加另一级别的复杂功能,我希望这个级别由groupname执行。

如果有人拥有SQL解决方案,PROC SQL就完全没问了。

使用上述数据,排名如下:

id     year_start     group_name     test_score     rank
1       19931231          Red            90         0.75
1       19941230          Red            89          0.8
1       19951231          Red            91           1
1       19961231          Red            92           1
2       19930630          Red            85           1
2       19940629          Red            87          0.8
2       19950630          Red            95         0.75
3       19950931          Blue           90           1
3       19960931          Blue           90           1
4       19930331          Red            95           1
4       19940331          Red            97          0.2
4       19950330          Red            98          0.2
4       19960331          Red            95         0.333
5       19931231          Red            96         0.25
5       19941231          Red            97         0.667

为了计算第1行的等级,

  • 我们首先排除蓝色观察。
  • 然后我们计算那年之前一年内的观测数量_开始,19931231(所以我们有4次观测)。
  • 我们计算这些观察中有多少具有更高的test_score,然后加1以找到当前观察的顺序(因此它是第3高)。
  • 然后,我们将订单除以总数得到等级(3/4 = 0.75)。

在Excel中,此变量的公式看起来像这样。假设公式适用于第1行,有100行。 id = A,year_start = B,groupname = C,test_score = D:

      =(1+countifs(D1:D100,">"&D1, 
                B1:B100,"<="&B1,
                B1:B100,">"&B1-365.25,
                C1:C100, C1))/
       countifs(B1:B100,"<="&B1,
                B1:B100,">"&B1-365.25,
                C1:C100, C1) 

非常感谢你的帮助!

ahammond428

2 个答案:

答案 0 :(得分:1)

如果我正确地阅读它,你的例子是不正确的,所以很难确切知道你想要做什么。但请尝试以下操作,看看它是否有效。您可能需要调整不等式是否可以打开或关闭,具体取决于您是否要在该日期中包含一年。请注意,您的year_start列需要以SAS日期格式导入才能生效。否则你可以用输入(year_start,yymmdd8。)来改变它。

proc sql;
select distinct
    a.id,
    a.year_start,
    a.group_name,
    a.test_score,
    1+sum(case when b.test_score > a.test_score then 1 else 0 end) as rank_num,
    count(b.id) as rank_denom,
    calculated rank_num / calculated rank_denom as rank
from testdata a left join testdata b
    on a.group_name = b.group_name
    and intnx('year',a.year_start,-1,'s') le b.year_start le a.year_start
group by a.id, a.year_start, a.group_name, a.test_score
order by id, year_start;
quit;

请注意,我将9/31的日期更改为9/30(因为没有9/31),但仅剩下3月30日,6月29日和12月30日,因为这可能是预期的,尽管另一个约会似乎是四分之一。

答案 1 :(得分:0)

考虑SQL中的相关计数子查询:

数据

data ranktable;   
    infile datalines missover;  
    input id year_start group_name $ test_score; 
    datalines; 
1       19931231          Red            90
1       19941230          Red            89
1       19951231          Red            91
1       19961231          Red            92
2       19930630          Red            85
2       19940629          Red            87
2       19950630          Red            95
3       19950930          Blue           90
3       19960930          Blue           90
4       19930331          Red            95
4       19940331          Red            97
4       19950330          Red            98
4       19960331          Red            95
5       19931231          Red            96
5       19941231          Red            97
; 
run;

data ranktable;
    set ranktable;          
    format year_start date9.;
    year_start = input(put(year_start,z8.),yymmdd8.);
run;

PROC SQL

审核中包含的其他字段

proc sql;
    select r.id, r.year_start, r.group_name, r.test_score, 
           put(intnx('year', r.year_start, -1, 's'), yymmdd10.) as year_ago,
           (select count(*) from ranktable sub 
            where sub.test_score >= r.test_score
            and sub.group_name = r.group_name
            and sub.year_start <= r.year_start
            and sub.year_start >= intnx('year', r.year_start, -1, 's')) as num_rank,    
           (select count(*) from ranktable sub 
            where sub.group_name = r.group_name
            and sub.year_start <= r.year_start
            and sub.year_start >= intnx('year', r.year_start, -1, 's')) as denom_rank,    
           calculated num_rank / calculated denom_rank as rank
    from ranktable r;
run;

<强>输出

您会注意到您的预期结果之间存在细微差异,这可能是由于您申请所有年份的季度日(365.25),因为SAS intnx需要一整天的日历年随着每年的变化

Proc SQL Output