SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 1950|回复: 12
打印 上一主题 下一主题

求助:一个折磨了我很久的问题

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2009-7-7 23:45:09 | 只看该作者

求助:一个折磨了我很久的问题

数据集是这样子的:
code  date  p  
1       1-1    1.1
1       1-2    1.2
1       1-3    1.1
1       1-4    1.5
1       1-5    1.7
2       1-1    2.1
2       1-2    2.2
2       1-3    1.6
2       1-4    1.5
2       1-5    1.9
3       1-1    1.3
3       1-2    1.4
3       1-3    1.6
3       1-4    1.1
3       1-5    1.0
...
问题:1,求新字段cmp    cmp(t)=max(p(t)~p(t-2))-min(p(t)~p(t-2)))  ;即,这些code,在每个日期(date),对应一个cmp(t) 它是临近3天该code的最大和最小的p的差;
2、生成新的字段 dh  dh(t)=median(p(t)~p(t-2))  即,对每个code  在每个日期(date),对应一个dh(t) 它是该code临近的三天的p的中位数。
注意:上述的计算在code之间不能交叉。

那位高人能出手帮忙,在下感激不尽!
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2009-7-8 10:19:54 | 只看该作者

Re: 求助:一个折磨了我很久的问题

最大最小值的一问,我倒是有了一个解决的办法(我的办法很土,也望高人再指点);但是median的一问还望高人指点一下啊
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2009-7-8 14:58:34 | 只看该作者

Re: 求助:一个折磨了我很久的问题

看看是这样吗?

[code:2sp6r820]data aaa;
        input code date $ p;
        datalines;
1 1-1 1.1
1 1-2 1.2
1 1-3 1.1
1 1-4 1.5
1 1-5 1.7
2 1-1 2.1
2 1-2 2.2
2 1-3 1.6
2 1-4 1.5
2 1-5 1.9
3 1-1 1.3
3 1-2 1.4
3 1-3 1.6
3 1-4 1.1
3 1-5 1.0
;

data bbb (drop=n);
        set aaa;
        by code;

        if first.code then n=1;
        else n+1;

        cmp=max(p,lag1(p),lag2(p))-min(p,lag1(p),lag2(p));
        dh=median(p,lag1(p),lag2(p));

        if n lt 3 then call missing(cmp,dh);
run;[/code:2sp6r820]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2009-7-8 17:13:09 | 只看该作者

Re: 求助:一个折磨了我很久的问题

十分感谢hopewell兄,就是这个意思。但我在上面列的数据集是一个样例,处理的实际数据比较大,求中值和最值时面临的样本区间也比较长(比如是一个100日的移动窗口),代码能扩展一下解决这个问题么?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2009-7-8 23:51:01 | 只看该作者

Re: 求助:一个折磨了我很久的问题

不知道效率如何?还有更好的方法吗?

[code:bmlg1jmx]/* 设定滞后量 */
%let lag_n=10;

/* 创建模拟数据 */
data raw_data;
        do code=1 to 100;
                do date='01jan09'd to '30jan09'd;
                        p=ceil(10*ranuni(123));
                        output;
                end;
        end;
        format date yymmdd10.;
run;

/* 拷贝模拟数据 */
data copy_data;
        set raw_data;
        rename code=copy_code
                date=copy_date
                p=copy_p
                ;
run;

/* 使用HASH ITERATOR创建中间变量 */
data temp_data(drop=copy_code copy_date copy_p rc);
    if _n_=1 then
        do;
           declare hash p_hash(dataset:'copy_data',hashexp:10,ordered:'ascending');
           p_hash.definekey ('copy_code','copy_date');
           p_hash.definedata('copy_code','copy_date','copy_p');
           p_hash.definedone();
           call missing(copy_code,copy_date,copy_p);

           declare hiter p_hiter('p_hash');
        end;

    set raw_data;
        length temp $500;
        flag=0;

    rc=p_hiter.first();
    do while(rc eq 0);
        if (code=copy_code) and (0<=date-copy_date<&lag_n) then
            do;       
                                if flag=0 then temp=cat(copy_p);
                                        else temp=catx(',',temp,copy_p);
                                flag+1;
            end;
        rc=p_hiter.next();
    end;
run;

/* 创建宏 */
%macro compute;
        %let dsid=%sysfunc(open(temp_data));
    %let nobs=%sysfunc(attrn(&dsid,nobs));

    %syscall set(dsid);

    %do i=1 %to &nobs;
            %let rc=%sysfunc(fetchobs(&dsid,&i));
                code=&code;
                date=&date;
                p=&p;
                %if &flag=&lag_n %then %do;
                                cmp=max(&temp)-min(&temp);
                                dh=median(&temp);
                        %end;
        output;
        %end;

    %let dsid=%sysfunc(close(&dsid));
%mend;

/* 调用宏 */
data final_data;
        %compute
        format date yymmdd10.;
run;[/code:bmlg1jmx]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
6#
 楼主| 发表于 2009-7-9 07:21:01 | 只看该作者

Re: 求助:一个折磨了我很久的问题

搞不懂楼主想要什么,但是楼上的洪让人敬仰,拜师之意油然而生。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
7#
 楼主| 发表于 2009-7-9 09:54:01 | 只看该作者

Re: 求助:一个折磨了我很久的问题

这段程序确实效率高!
有些地方没看懂,请教徐福贵一下:
1 set语句放在do组里之后,对数据集观测的读取顺序会有什么影响?
2 是因为do until先执行后判断,所以才能把by语句放到do组中的吗(即先有last.code,后有by语句)?
谢谢!

[code:3i27qher]data final_data2(drop=index);
   array pp[0:%eval(&lag_n-1)] _temporary_;        /* 创建数组,下标0-9 */
   index = 0; /* 为下标变量赋初值 */

   /* 把set语句用在do组中,我还是头次见 */
   do _n_=1 by 1 until(last.code); /* 在每个code组中循环 */
      set raw_data;        /* ??? */
      by code; /* ??? */

      pp[index] = p; /* 为数组元素赋p值 */
      index = mod(index+1, &lag_n);        /* 下标变量+1,取模保证值域为0-9 */
          /* 计算部分 */
      if _n_>=&lag_n then do;
         cmp = max(of pp[*]) - min(of pp[*]);
         dh = median(of pp[*]);
      end;
      output;
   end;
run;[/code:3i27qher]
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
8#
 楼主| 发表于 2009-7-9 12:26:34 | 只看该作者

Re: 求助:一个折磨了我很久的问题

我也不知道怎么解释,我最想做的是拜您为师,

题外话,我还想找个老伴,我看维族人民英雄Rabiye Qadir不错, 可惜她家的老头子还没不致哪天死,就算死了也不知道看不看得上我一个泥巴腿子,让我没个盼头。家珍一定不会怪我的,她只会为我这向上的念头在墓中激赏不已!
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
9#
 楼主| 发表于 2009-7-9 21:27:18 | 只看该作者

谢谢徐福贵的PDF

<!-- s:( --><img src="{SMILIES_PATH}/icon_sad.gif" alt=":(" title="Sad" /><!-- s:( --> 生活真不美好,一觉醒来猛然发现DO循环已不副当初的模样...
SAS到底该怎么学呀?
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
10#
 楼主| 发表于 2009-7-10 11:52:02 | 只看该作者

Re: 求助:一个折磨了我很久的问题

这里高手真多,谢谢大家
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|Archiver|SAS中文论坛  

GMT+8, 2026-2-5 19:39 , Processed in 0.069962 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表