楼主: moyunzheng
8282 11

一对多横向合并数据的问题(非merge by) [推广有奖]

  • 1关注
  • 2粉丝

博士生

60%

还不是VIP/贵宾

-

威望
0
论坛币
1358 个
通用积分
0.0035
学术水平
18 点
热心指数
19 点
信用等级
17 点
经验
11986 点
帖子
240
精华
0
在线时间
360 小时
注册时间
2010-12-11
最后登录
2023-9-6

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
多是icd编码,如A00,第一位是字母,后两位是数字,有很多重复。
一是分类的icd编码范围,如A00A09,表示从A00-A09共十个icd编码,范围为连续,无重叠(一个icd编码只属于一个分类)。

猜想如下:
用宏取得icd编码对应的范围,这减少data步的次数,用set语句的point=选项直接跳到未对比过的观测。
由宏返回编码范围,if语句查看,直到取得icd编码对应的范围为止。
if语句判断时字母用ascii码判断,数据直接运算。

问题:
宏调用未返回任何值。请问更位高手,这类问题应该用什么方法解决。

可能原因:
data步中,如果call execute产生sas language statements,或者macro language elements产生sas language statements,这些statements在当前data step执行后执行。
参考:
[url=http://sasor.feoh.net/viewtopic.php?f=1&t=1178http://tj.100xuexi.com/HP/20100121/OTD47955.shtml]http://sasor.feoh.net/viewtopic.php?f=1&t=1178http://tj.100xuexi.com/HP/20100121/OTD47955.shtml[/url]

note如下:
NOTE: 数值已转换为字符值,位置:(行:列)。
      1499:42
NOTE: 变量 FIRST.icdtemp 未初始化。


程序如下:

data death;
input icdtemp $ @@;
cards;
A03 A03 A09 A09 A15 A15 A15 A15
A16 A16 A16 A16 A17 A18 A31 A35
A35 A39 A39 A40 A41 A41 A46 A46 A48
A86 A86 A86 A87 A87
;
run;
data icd;
input group subgroup icdsubcode $;
cards;
1 1 A00A09
1 2 A15A19
1 3 A20A28
1 4 A30A49
1 5 A50A64
1 6 A65A69
1 7 A70A74
1 8 A75A79
1 9 A80A89
1 10 A90A99
1 11 B00B09
1 12 B15B19
1 13 B20B24
1 14 B25B34
1 15 B35B49
1 16 B50B64
1 17 B65B83
1 18 B85B89
1 19 B90B94
1 20 B95B97
1 21 B99B99
2 1 C00C97
2 2 D00D09
2 3 D10D36
;
run;
proc sort data=death;by icdtemp;run;
proc sort data=icd;by icdsubcode;run;

%macro getsubcode(pointer);
%global stra strb numa numb icdsubcode;
%local pointer;
data deathtemp;
pointer=%eval(&pointer);
set icd point=pointer;
a=substr(left(upcase(icdsubcode)),1,1);
b=substr(left(upcase(icdsubcode)),4,1);
c=substr(left(upcase(icdsubcode)),2,2);
d=substr(left(upcase(icdsubcode)),5,2);
call symputx("stra",a);
call symputx("strb",b);
call symputx("numa",c);
call symputx("numb",d);
call symputx("icdsubcode",icdsubcode);
output;
stop;
run;
%mend getsubcode;


data death2;
set death;
retain pointer  icdsubcode;
i=1;strtemp=rank(substr(left(icdtemp),1,1));numtemp=put(substr(left(icdtemp),2,2),2.);
if FIRST.icdtemp then do;
                do while (i=1);
                        pointer+1;
                        call execute('%getsubcode('||pointer||')');
                                a='&stra';b='&strb';c='&numa';d='&numb';e='&icdsubcode';
                                m1=resolve(a);m2=resolve(b);m3=resolve(c);m4=resolve(d);m5=resolve(e);
                        if  strtemp >= rank(m1) and strtemp <= rank(m2) and numtemp >=m3 and numtemp <=m4
                                then do;
                                icdsubcode=m5;
                                i=0;
                                end;
                end;
        end;
output;
run;


补充:
最后我用sql实现了,但是还是想问问如果不用sql怎么实现,因为担心数据量大的话sql效率的问题
sql的如下:
data death;
input icdtemp $ @@;
cards;
A03 A03 A09 A09 A15 A15 A15 A15
A16 A16 A16 A16 A17 A18 A31 A35
A35 A39 A39 A40 A41 A41 A46 A46 A48
A86 A86 A86 A87 A87
;
run;
data icd;
input group subgroup icdsubcode $;
cards;
1 1 A00A09
1 2 A15A19
1 3 A20A28
1 4 A30A49
1 5 A50A64
1 6 A65A69
1 7 A70A74
1 8 A75A79
1 9 A80A89
1 10 A90A99
1 11 B00B09
1 12 B15B19
1 13 B20B24
1 14 B25B34
1 15 B35B49
1 16 B50B64
1 17 B65B83
1 18 B85B89
1 19 B90B94
1 20 B95B97
1 21 B99B99
2 1 C00C97
2 2 D00D09
2 3 D10D36
;
run;
data death;
set death;
strtemp=rank(substr(left(icdtemp),1,1));
numtemp=put(substr(left(icdtemp),2,2),2.);
run;
data icd;
set icd;
a=rank(substr(left(upcase(icdsubcode)),1,1));
b=rank(substr(left(upcase(icdsubcode)),4,1));
c=put(substr(left(upcase(icdsubcode)),2,2),2.);
d=put(substr(left(upcase(icdsubcode)),5,2),2.);
run;
proc sort data=death;by icdtemp;run;
proc sort data=icd;by a b c d;run;
proc sql ;
create table deathtotal as select * from death join icd on strtemp>=a and strtemp<=b and numtemp>=c and numtemp<=d;
run;


二维码

扫码加我 拉你入群

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

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

关键词:Merge 合并数据 一对多 Statements statement 字母

本帖被以下文库推荐

沙发
jingju11 发表于 2011-9-21 08:57:42 |只看作者 |坛友微信交流群
NOTE: 变量 FIRST.icdtemp 未初始化。
原因是你没有by statement。
这里用call execute不妥当。CALL EXECUTE ,RESOLVE都类似于所谓的穿越,不同界面之间的。我试了一下,400×6000的表格用sql也不过一两分钟。用random access也可以。时间和sql基本相当。另外,我没有仔细研究你的程序。但是我觉得你对point的理解不是完全的没有错误。
使用rank没有很大的必要,sas的字符串是可以直接比较的。比如'A005' <'A006'是成立的
你的sql程序我没有运行出结果。

京剧
京剧

使用道具

藤椅
soporaeternus 发表于 2011-9-21 09:21:44 |只看作者 |坛友微信交流群
一变成start-end形式
多的用类似between去做匹配
需要严格匹配的话可以在连接条件中拆分AXXX为A XXX

是我理解的太简单了,还是楼主理解的太复杂了?
Let them be hard, but never unjust

使用道具

板凳
leedx 发表于 2011-9-21 09:33:52 |只看作者 |坛友微信交流群
学习一下,呵呵~~~

使用道具

报纸
jingju11 发表于 2011-9-21 11:52:32 |只看作者 |坛友微信交流群
soporaeternus 发表于 2011-9-21 09:21
一变成start-end形式
多的用类似between去做匹配
需要严格匹配的话可以在连接条件中拆分AXXX为A XXX
谁是楼主?呵呵。
攀龙附凤:我的理解也是如此。
而且如果简单的做,好像在这里拆分都不需要:
比如 WHERE X BETWEEN SUBSTR(Y, 1, 3) AND SUBSTR(Y, 4) ---SQL;
IF X GE SUBSTR(Y, 1, 3) AND X LE SUBSTR(Y, 4) ---POINT= +set;
顺便瞎说一句:从某种意义上讲,macro所产生的效率。通常都不是机器运行的效率。只不过少写些程序而已。如果吹毛求疵,macro应该降低效率,因为如果要和其他interface结合,它至少多了一道自身编译的过程。
jingju

使用道具

地板
moyunzheng 发表于 2011-9-21 13:16:58 |只看作者 |坛友微信交流群
jingju11 发表于 2011-9-21 08:57
原因是你没有by statement。
这里用call execute不妥当。CALL EXECUTE ,RESOLVE都类似于所谓的穿越,不同 ...
谢谢。
对因为对各种运算还不太熟悉,所以想的方法比较笨。
关于sql结果的问题
如果程序如下,能够得到视图,但是note还是显示
proc sql ;
select * from death join icd on strtemp>=a and strtemp<=b and numtemp>=c and numtemp<=d;
NOTE: 执行该查询涉及到执行无法优化的一个或多个笛卡尔乘积连接。

如果多加了个create table,可以得到结果,结果也是正确的,也会有note
proc sql ;
create table deathtotal as select * from death join icd on strtemp>=a and strtemp<=b and numtemp>=c and numtemp<=d;
NOTE: 执行该查询涉及到执行无法优化的一个或多个笛卡尔乘积连接。
NOTE: 表 WORK.DEATHTOTAL 创建完成,有 30 行,10 列。

但是如果我用3万多条的数据做的时候,


使用道具

7
moyunzheng 发表于 2011-9-21 13:17:48 |只看作者 |坛友微信交流群
soporaeternus 发表于 2011-9-21 09:21
一变成start-end形式
多的用类似between去做匹配
需要严格匹配的话可以在连接条件中拆分AXXX为A XXX
因为不知道有between,所以想的过程复杂了

使用道具

8
moyunzheng 发表于 2011-9-21 13:21:59 |只看作者 |坛友微信交流群
jingju11 发表于 2011-9-21 11:52
谁是楼主?呵呵。
攀龙附凤:我的理解也是如此。
而且如果简单的做,好像在这里拆分都不需要:
再问个简单的问题,字母的比较是大小写区分的吧?是不是都要做upcase()或者lowcase()。谢谢啦

使用道具

9
soporaeternus 发表于 2011-9-21 13:55:12 |只看作者 |坛友微信交流群
moyunzheng 发表于 2011-9-21 13:21
再问个简单的问题,字母的比较是大小写区分的吧?是不是都要做upcase()或者lowcase()。谢谢啦
嗯...
抱歉,您的帖子小于 10 个字符的限制
Let them be hard, but never unjust

使用道具

10
jingju11 发表于 2011-9-21 21:16:14 |只看作者 |坛友微信交流群
moyunzheng 发表于 2011-9-21 13:21
再问个简单的问题,字母的比较是大小写区分的吧?是不是都要做upcase()或者lowcase()。谢谢啦
是的。建议你在单个的数据集里做。如果你的data真的很大。一个是30k,一个是?
京剧

使用道具

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

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-28 16:12