全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 SAS专版
3005 12
2011-04-13
刚刚接触SAS不到3个月,还有很多不懂的地方。最近在做一个课程的小project,编程思路上被卡住了,希望高人能够指点以下。
因为只知道数据可以横向处理,像这种带条件的,不规则的,还是纵向处理数据的project还是第一次碰到。

比如我有数据如下:

公司            日期1(D1)      日期2(D2)             金额A (PA)      金额B(PB)
A               2001.03.01       2001.03.30               100                150
A               2001.03.06       2001.03.30               100                120
A               2001.03.29       2001.03.30               100                90
A               2001.04.01       2001.04.30                200               160
A               2001.04.15       2001.04.30                200               180
A               2001.04.20       2001.04.30                200               190      
A               2001.04.28       2001.04.30                200               180
B               2001.03.01       2001.03.30               105                112
B               2001.03.08       2001.03.30               105                110
B               2001.03.28       2001.03.30               105                60
B               2001.04.05       2001.04.30               100                90
B               2001.04.16       2001.04.30               100                80
B               2001.04.27       2001.04.30               100               105      
B               2001.04.28       2001.04.30               100               110
B               2001.04.29       2001.04.30               100               110

现在,打算实现如下运算。
计算1:
以“日期2”为基准,如果“日期1”是在“日期2”之前的30天之内,则把这些“日期1”所对应的“金额B”取平均值,得到“基数A”,之后用“金额A”减去“基数A”。

计算2:
以“日期2”为基准,取“日期1”中距离“日期2”最近的一天,把该“日期1”所对应的“金额B”作为“基数B”,之后用“金额A”减去“基数B”。

因为有不同的公司,每个公司又有不同年份和月份,所以总共有将近300万个数据。
要求把结果按照公司和年份分类,观察得到的差值变化。
想了3天,到现在没有任何思路。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

全部回复
2011-4-13 13:49:27
try to use
proc sql;
group by 公司,      日期2(D2)
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2011-4-13 18:26:08
这两个计算都是要先按公司和年份划分吗?

比如,计算1,如果只有你给的这15条数据,7条A公司8条B公司,所有数据都是符合你的D2 - D1 <=30的条件的。那么计算基数A的时候,是15个金额取平均呢,还是对A公司的7条取平均,对B公司的8条取平均?

年份也是类似,比如,如果有A公司有20条数据符合D2-D1<=30,其中8条是2001年的,12条是2002年的,算基数A需要根据年份分开么?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2011-4-13 22:11:00
3# myc_sas
你好,是的,年份和公司都要分开取
也就是说A公司2001年3月和4月要分开取平均值
B公司也同样。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2011-4-13 22:35:44
我昨天想破头,编了下面这个程序,目前只能实现一半我需要的功能。实际上,我想要得到的平均值,就是以不同的公司和“日期2”来划分的。

之前先数据处理,同一家公司,D1-D2范围大于30天的数据,进行删除。其中公司是用代码来表示的,比如公司1和公司2。

然后进行如下操作

data test;
set dansas.test;
dummy_date+0;
dummy_company+0;  /* Initial dummy value is zero*/

do i=1 to 1;
if company=dummy_company and d2=dummy_date then
do j=1 to 1;
total_p2+p2;
no+1;
mean_p2=total_p2/no;
end;
else
do k=1 to 1;
total_p2=0;
no=1;
dummy_date=d2;
dummy_company=company;
total_p2=p2;
mean_p2=total_p2/no;
end;
end;
run;

proc print data=test;
var  dummy_date dummy_company p2 total_p2 mean_p2;
run;

结果会得到如下运行结果:
公司            日期1(D1)      日期2(D2)             金额1 (P1)      金额2(P2)   个数(NO) 累加金额2(total_P2)  平均金额2(mean_p2)
1               2001.03.01       2001.03.30               100                150               1                   150                                  150
1               2001.03.06       2001.03.30               100                120               2                   270                                  135
1               2001.03.29       2001.03.30               100                90                 3                   360                                  120 (需要)
1               2001.04.01       2001.04.30                200               160               1                   160                                  160
1               2001.04.15       2001.04.30                200               180               2                   340                                  170
1               2001.04.20       2001.04.30                200               190               3                   530                                  176.7
1               2001.04.28       2001.04.30                200               180               4                   710                                  177.5(需要)
2               2001.03.01       2001.03.30               105                112               1                   112                                  112
2               2001.03.08       2001.03.30               105                110               2                   222                                  111
2               2001.03.28       2001.03.30               105                60                 3                   282                                   94  (需要)
2               2001.04.05       2001.04.30               100                90                 1                   90                                     90
2               2001.04.16       2001.04.30               100                80                 2                   170                                   85
2               2001.04.27       2001.04.30               100               105                3                   275                                   91.5
2               2001.04.28       2001.04.30               100               110                4                   385                                   96.3
2               2001.04.29       2001.04.30               100               110                5                   495                                   99(需要)


可以看出,我做的平均值实际上就是“累加金额2”除以前面的“累加个数”。但实际上,只有每个“日期2”周期内,最后一个“日期1”所对应的平均值才是真实我想要的30天内的"金额2"的平均值。
然后,我需要用“金额1”减去这个“需要”的“平均值”,在把这些数字从表格中提取出来。
现在的问题是,如何可以只把需要的那几行数字提取出来。我如果仅仅用“金额1”减去“平均值”,列在前面的几个结果,实际上是无效的。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2011-4-14 08:03:03
由于你的数据量大,建议你使用hash。
data sample1;
input co$ 1.  date1 yymmdd11. date2 yymmdd11.  pa pb;
cards;
A 2001-03-01 2001-03-30 100 150
A 2001-03-06 2001-03-30 100 120
A 2001-03-29 2001-03-30 100 90
A 2001-04-01 2001-04-30 200 160
A 2001-04-15 2001-04-30 200 180
A 2001-04-20 2001-04-30 200 190      
A 2001-04-28 2001-04-30 200 180
B 2001-03-01 2001-03-30 105 112
B 2001-03-08 2001-03-30 105 110
B 2001-03-28 2001-03-30 105 60
B 2001-04-05 2001-04-30 100 90
B 2001-04-16 2001-04-30 100 80
B 2001-04-27 2001-04-30 100 105      
B 2001-04-28 2001-04-30 100 110
B 2001-04-29 2001-04-30 100 110
;
run;
data result;
length co $ 1;
/*定义部分*/
if _n_=1 then do;
        declare hash h1();
        h1.definekey('co','date2');
        h1.definedata('co','date2','count','ave','total');
        h1.definedone();
        call missing(total,ave,count);
        declare hiter iter1('h1');
end;
/*选择满足要求的记录进入哈希表并累加,计数*/
do until(last);
        set sample1 end=last;        
        if h1.find()=0 and date2-date1<30 then do;
                count+1;
                total+pb;
                h1.replace();
        end;
    if h1.find()^=0 and date2-date1<30 then do;
                total=pb;
                count=1;
                h1.add();
        end;
end;
/*遍历并计算输出*/
        rc=iter1.first();
        do while(rc=0);
                ave=total/count;
                name=pa-ave;
                output;
                rc=iter1.next();
        end;
run;
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

点击查看更多内容…
相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群