SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 2483|回复: 10
打印 上一主题 下一主题

data步数据处理难题求助,希望获得高手的指点。

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2007-3-25 20:44:55 | 只看该作者

data步数据处理难题求助,希望获得高手的指点。

我现在有这样一个数据集( AAA):

Prod,Prom_1,Prom_2,Prom_3,Prom_4,Prom5
1001,12,23,34,45,,
1001,12,26,34,56,,
1002,23,24,,,,
1002,23,25,35,,,
1002,23,45,,,,
……
我还有一张表(BBB),记录Prod按规定只能搭配的Prom,如下表中按规定1001这个Prod只能搭配12、23这两个Prom,其他的都应该是不允许的。
Prod,Prom
1001,12
1001,23
1002,23
1002,25
1002,45
1003,12
……

现在我希望对数据集AAA做如下操作:
对每一条记录进行判断,先找到Prod,然后对比BBB表中该Prod能搭配的Prom,在AAA表中每条记录后标记该条记录的Prod是否搭配了BBB表中不允许搭配的Prom。例如AAA表中第一条记录1001,12,23,34,45中的1001搭配了不允许的34、45两个Prom,那么就在后面增加一个字段Invalid=“34||45”

AAA表处理后的结果示例如下:
Prod,Prom_1,Prom_2,Prom_3,Prom_4,Prom5,[b:622b0][color=red:622b0]Invalid[/color:622b0][/b:622b0]
1001,12,23,34,45,,[b:622b0][color=red:622b0]34||45[/color:622b0][/b:622b0]
1001,12,26,34,56,,[b:622b0][color=red:622b0]26||34||56[/color:622b0][/b:622b0]
1002,23,24,,,,[b:622b0][color=red:622b0]24[/color:622b0][/b:622b0]
1002,23,25,35,,,[b:622b0][color=red:622b0]35[/color:622b0][/b:622b0]
1002,23,45,,,,,
……

请高手指点一下该如何写实现这个功能的一段代码,不甚感激!
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2007-3-25 20:58:18 | 只看该作者

后续的问题

同样还是针对数据集AAA
Prod,Prom_1,Prom_2,Prom_3,Prom_4,Prom5
1001,12,23,34,45,,
1001,12,26,34,56,,
1002,23,24,,,,
1002,23,25,35,,,
1002,23,45,,,,
……

还有另外一张表(CCC),记录Prom和 Prom之间不能搭配的关系,如下表中所示[color=red:ea64b][b:ea64b]12、23[/b:ea64b][/color:ea64b]这两个促销是不允许同时搭配的。

Prom1,Prom2
[color=red:ea64b][b:ea64b]12,23[/b:ea64b][/color:ea64b]
34,45
12,26
23,25
23,45
……

现在希望对数据集AAA做如下操作:
对每一条记录进行判断,看是否存在表CCC不允许同时搭配的两个Prom,例如AAA表中第一条记录1001,12,23,34,45中的[color=red:ea64b][b:ea64b]12和23[/b:ea64b][/color:ea64b]是不允许同时搭配的,[b:ea64b][color=red:ea64b]34和45[/color:ea64b][/b:ea64b]也是不允许同时搭配的。那么就在记录后增加一个字段Invalid=“[color=red:ea64b][b:ea64b]12-23||34-45[/b:ea64b][/color:ea64b]”

AAA表处理后的结果示例如下:
Prod,Prom_1,Prom_2,Prom_3,Prom_4,Prom5,invalid
1001,12,23,34,45,,[color=red:ea64b][b:ea64b]12-23||34-45[/b:ea64b][/color:ea64b]
1001,12,26,34,56,,[b:ea64b][color=red:ea64b]12-26[/color:ea64b][/b:ea64b]
1002,23,24,,,,,
1002,23,25,35,,,[b:ea64b][color=red:ea64b]23-25[/color:ea64b][/b:ea64b]
1002,23,45,,,,[b:ea64b][color=red:ea64b]23-45[/color:ea64b][/b:ea64b]
……

这段代码又如何写呢?谢谢指点!
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2007-3-26 14:22:36 | 只看该作者

re no.1

data a;
input Prod Prom_1 Prom_2 Prom_3 Prom_4 Prom_5 ;
datalines;
1001 12 23 34 45   .
1001 12 26 34 56  .
1002 23 24 .  .  .
1002 23 25 35  . .
1002 23 45  . . .   
;run;

data b;
   input Prod Prom ;
   cards;
1001 12
1001 23
1002 23
1002 25
1002 45
1003 12
;run;

proc transpose data=b out=b_2;
      by prod;
      run;

data a_2;
   set a;
     prom=compbl(compress(prom_1||' '||prom_2||' '||prom_3||' '||prom_4||' '||prom_5,'.'));
run;

proc sql;
      select max(varnum) into : no from sashelp.vcolumn where memname='B_2';quit;

%macro test;
data c;
   merge a_2(in=a) b_2;
       by prod;
       if a;
       invalid=prom;
      %do i=1 %to %eval(&no-2);
            invalid=tranwrd(invalid,compress(col&i.),' ');
      %end;

     if invalid ne '' then  invalid=tranwrd(trim(left(invalid)),' ','||');
     keep Prod Prom_1 Prom_2 Prom_3 Prom_4 Prom_5 invalid;
run;

%mend;
%test;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2007-3-26 14:25:18 | 只看该作者

re no.2

这个似乎比较简单了

data a;
n=_n_;
input Prod Prom_1 Prom_2 Prom_3 Prom_4 Prom_5 ;
datalines;
1001 12 23 34 45   .
1001 12 26 34 56  .
1002 23 24 .  .  .
1002 23 25 35  . .
1002 23 45  . . .   
;run;
data d;
  input Prom1 Prom2;
     cards;
12 23
34 45
12 26
23 25
23 45
;run;


proc sql;
       create table e as  select * from a, d order by n;quit;

data e_2;
       set e;
            if prom1=prom_1 or prom1=prom_2 or prom1=prom_3 or prom1=prom_4 or prom1=prom_5 then flag1=1;
            if prom2=prom_1 or prom2=prom_2 or prom2=prom_3 or prom2=prom_4 or prom2=prom_5 then flag2=1;
            if flag1 ne 1 or flag2 ne 1 then delete;
       promm=compress(prom1||'-'||prom2);
run;
proc transpose data=e_2 out=f(drop=_name_ n);
        var promm;
        by  n Prod Prom_1 Prom_2 Prom_3 Prom_4 Prom_5 ;
       run;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2007-3-26 15:52:14 | 只看该作者

谢谢

谢谢dragonin的大力帮助,我试试看:)
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
6#
 楼主| 发表于 2007-3-26 23:14:25 | 只看该作者

谢谢

第一个问题看来最核心的还是tranwrd、compress、compbl等字符串函数的应用:)

关于第二个问题,我看明白了,你把 a, d 表连起来生成e表,然后在e表上操作就比较容易了。但是有一个问题:e表的纪录数=a表记录数*d表记录数;如果a表有10万条记录,d表也有几万条记录,那这样e表记录数狂多,是不是效率不高啊?看看是否还有其他解决办法。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
7#
 楼主| 发表于 2007-3-26 23:51:28 | 只看该作者

关于sashelp.vcolumn和sashelp.vtable

刚查看了一下关于sashelp.vcolumn,原来是meta tables(数据的数据),里面信息还不少。

proc sql;
select max(varnum) into : no from sashelp.vcolumn where memname='B_2';quit;

如果要取一张表的字段数,除了从sashelp.vcolumn中取之外,
还可以从sashelp.vtable中的nvar(Number of Variables)字段来取。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
8#
 楼主| 发表于 2007-3-28 13:49:58 | 只看该作者

Re: 关于sashelp.vcolumn和sashelp.vtable

Dictionary 表是一个只读SAS数据视图, 可通过它来实时获得当前SAS session的各种信息。
Dictionary.columns 相当于 sashelp.vcolumn
通过sashelp可以直接查看里面的各个变量名称。但在各种范例中,都会使用Dictionary,而不是sashelp.

另外,建议用proc sql来使用 Dictionary 表。如果将其用在Data步里,会慢很多。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
9#
 楼主| 发表于 2007-3-28 17:21:16 | 只看该作者

re

SAS does not maintain DICTIONARY table information between queries. Eachquery of a DICTIONARY table launches a new discovery process. Therefore, if youare querying the same DICTIONARY table several times in a row, then you can geteven better performance by creating a temporary SAS data set (by using the DATA step SET statement or PROC SQL CREATE TABLE AS statement) that includes the information that you want and running your query against that data set.


271  proc sql stimer ;
NOTE: SQL Statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

272     select * from dictionary.tables;
NOTE: SQL Statement used (Total process time):
      real time           3.25 seconds
      cpu time            0.78 seconds

272!                                    quit;
NOTE: PROCEDURE SQL used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


273  proc sql stimer ;
NOTE: SQL Statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

274     select * from sashelp.vtable;
NOTE: SQL Statement used (Total process time):
      real time           3.11 seconds
      cpu time            0.53 seconds

274!                                 quit;
NOTE: PROCEDURE SQL used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
10#
 楼主| 发表于 2007-4-4 15:19:53 | 只看该作者

为什么还要标题

[code:a139f]
data AAA ;
  infile datalines truncover;
  input Prod Prom_1 Prom_2 Prom_3 Prom_4 Prom5 ;
  datalines;
1001 12 23 34 45   
1001 12 26 34 56   
1002 23 24     
1002 23 25 35   
1002 23 45     
;
run;

data ccc;
  input Prom1 Prom2 ;
  CALL SYMPUT('Vnum',_n_);
  cards;
12 23
34 45
12 26
23 25
23 45
;
run;


DATA FINAL (KEEP=Prom_1 Prom_2 Prom_3 Prom_4 Prom5 Invalid);
  SET AAA;
  length invalid  $ 100;
  Invalid='';
  array PArr Prom_1 Prom_2 Prom_3 Prom_4 Prom5;
  do i=1 to &vnum;
    count=0;
    set CCC point=i;
    do over PArr;
      count=count+(PArr=prom1)+(PArr=prom2);
    end;
    if count>=2 then Invalid=compress(trim(invalid)||'||'||prom1||'-'||prom2);
  end;
  if substr(invalid,1,1)='|' then invalid=substr(invalid,3);
run;[/code:a139f]
楼上的签名档是在自谦吗?吼吼吼吼吼. 看过你三个贴子,每贴必用TRANSPOSE,狂汗中........................
一RUN完就发现楼主的举例中第一条就少了一组INVALID的信息.呵呵呵.
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-13 18:18 , Processed in 0.071263 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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