我的数据集如下所示。我想根据他前一天的表现对每个名字进行排名。如果class
的{{1}}在第t天排名为前10%(20%),则第t + 1天的sales
排名应为1(2)。同样,如果name
的{{1}}在第t天排名为最低10%,则第t + 1天的name
排名应为10.
sales
到目前为止我所做的是:
步骤1.按name
name
对数据进行排序
第2步。创建new_variable name date sales rank
a day1 11
b day1 20
c day1 15
d day1 8
a day2 12
b day2 21
c day2 16
d day2 9
a day3 7
b day3 14
c day3 12
d day3 10
和date
。我是每个sales
上名字i的确切排名。 i
衡量每个N
的观察总数。如果date
/ N
小于.1,则date
= 10,等等。这个新变量I
将是第t天N
的排名。
但是,我不知道如何将今天的排名Rank_previous
指定为第二天Rank_previous
。因为,我的数据集非常大,如果您有更有效的方法来解决这个问题,那将会很棒。
name
答案 0 :(得分:2)
计算排名的最简单方法是,不出所料,给出SAS的命名法,PROC RANK
。为此,必须先对数据进行排序by date
。
data have;
input name $ date $ sales;
datalines;
a day1 11
b day1 20
c day1 15
d day1 8
a day2 12
b day2 21
c day2 16
d day2 9
a day3 7
b day3 14
c day3 12
d day3 10
;;;;
run;
proc rank data=have out=ranks percent;
by date;
var sales;
ranks rank;
run;
percent
参数要求百分位数而非数字排名。可能为您提供所需排名的另一个选项是groups=10
,它会将所有值分配给十个组中的一个,但有时使用原始百分位数并自行分配(更好地处理关系等)更容易。您也可以使用descending
以相反的顺序进行分配,因为我不清楚您打算采用何种顺序。
当然,正如你想要 next 那天的排名一样,你需要有一个简短的datastep来将日期增加一个并重新合并,或者SQL连接,或者任何你偏爱。
答案 1 :(得分:1)
使用2组临时ARRAY:一组用于保存前一天的排名,另一组用于创建当天的排名。
当您点击当天的LAST.date时,您可以输出当天的所有信息,包括前几天的排名。然后,将今天的排名复制到前一天的排名。
这样,您只需在按日期和销售排序后对其进行一次数据处理。
答案 2 :(得分:1)
首先让我们加载比示例更多的数据:
data have;
input name $ date $ sales;
datalines;
a day1 11
b day1 20
c day1 15
d day1 8
a day2 12
b day2 21
c day2 16
d day2 9
e day2 1
f day2 90
g day2 99
h day2 2
i day2 70
j day2 39
k day2 1
l day2 16
m day2 90
a day3 7
b day3 14
c day3 12
d day3 10
;
run;
由于性能很重要,我会选择PROC MEAN(这是proc类的扩展版本,可以保留小计并且非常有效.class子句对应于proc类中的by子句)
proc means data=have noprint;
class date sales name;
output out=haveMean (where=(_type_ in (4,7)));
小计和细节由类型命名。省略where子句以找出哪种类型具有哪些数据。 现在合并 type 4: freq 从中获取当天活跃的销售人员数量和类型 7:详细信息
data salesSum;
merge haveMean (where=(_type_ eq 4) rename=(_freq_=numberPerDay) drop=name sales)
haveMean (where=(_type_ eq 7));
by date;
跟踪当天的订单编号,将其除以活跃销售人员的编号
retain orderInDay rank;
if first.date then orderInDay = 1; else orderInDay = orderInDay+ 1;
仅计算具有特定销售量的第一次观察的等级,给出相同的等级
if first.date or lag1(sales) NE sales then rank = ceil(10 * orderInDay / numberPerDay);
打印相关内容
proc print data=salesSum;
by date;
var name sales rank;
run;
此解决方案仍然错过了将排名移至下一个工作日的方法。我考虑为此使用哈希表。
答案 3 :(得分:1)
**首先让我们加载比示例更多的数据:**;
data have;
input name $ date $ sales;
datalines;
a day1 11
b day1 20
c day1 15
d day1 8
a day2 12
b day2 21
c day2 16
d day2 9
e day2 1
f day2 90
g day2 99
h day2 2
i day2 70
j day2 39
k day2 1
l day2 16
m day2 90
a day3 7
b day3 14
c day3 12
d day3 10
e day4 1
f day4 90
g day4 99
h day4 2
i day4 70
j day4 39
k day4 1
l day4 16
m day4 90
;
run;
**然后,正如Joe教导我们的那样,让我们应用proc等级。我们需要排名,而不是销售,所以让我们摆脱它**;
proc rank groups=10
data=have
out=ranks (drop=sales);
by date;
var sales;
ranks rank_previous;
run;
**现在将前一天的排名与今天的销量合并,我们需要一点点memery **;
data have_memory;
set have;
by date;
retain date_previous;
if first.date then date_previous = lag1(date);
run;
**现在经典合并可以完成工作**;
data have_ranked (drop=date_previous);
merge have_memory (in=has)
ranks (rename=(date=date_previous));
by date_previous name;
if not has then date = 'next';
run;