【SAS Says·扩展篇】移形换影 | 5. call PRXCHANGE()
0. 前集回顾
1. 新的问题
2. 初识 PRXCHANGE()
3. 问题解决
0. 前集回顾:
前面说到,小王刚刚毕业,来到数说国际零售公司任数据分析师,帮助产品部的妹子解决了一个问题,下面是一份产品名单,有的行是产品的名字,有的行是产品的编号,现在只想将编号保留下来(即红色字体的部分),并且把括号里的数字再单独提出来(括号里的数字代表了产品的类别)、把有PD(代表过期产品)的标识也提取出来:
(01)1872-8756 Body shop P1 Book B13 (05)9212-0098 PD(05)9206-4571 Shushuo phone (12) 6753-5513 None here PD(12)6434-4532 P&D Washing PC Pro4321S: (09) 1352-3154
小王的SAS代码如下:
data production; if _N_=1then pattern=PRXPARSE("/(P?D?)((dd)) ?d{4}-d{4}/"); retain pattern; input name $char40.; length id $ 20; call PRXSUBSTR(pattern,name,start,length); *下面的PRXPOSN必须要配合这个PRXMATCH使用; match =PRXMATCH(pattern, name); if length GT 0thendo; *得到产品整个ID; id=substr(name,start,length); id=compress(id," "); *得到ID中的产品类型(即括号里面的数字); call PRXPOSN(pattern, 2, start_2, length_2); category=substr(name, start_2, length_2); *得到ID中产品的过期信息; call PRXPOSN(pattern, 1, start_1, length_1); if length_1 gt 0then pd= substr(name, start_1, length_1); output; end; keep id category pd; datalines; (01)1872-8756 Body shop P1 Book B13 (05)9212-0098 PD(05)9206-4571 Shushuophone (12)6753-5513 None here PD(12)6434-4532 P&DWashing PC Pro4321S:(09) 1352-3154 ; procprintnoobs; title'Production ID'; run;
得到最终的结果:
点击这里回顾前面几集:
- 提取文本数据,分析师小王初上手!
- 正则表达式的“阿赖耶识”
- 庖丁解牛切割数据!
- 撕数据! |【SAS Says·扩展篇】
1. 新的问题
糟糕!
所有编号的后面八位数字颠倒了!
XXXX-YYYY,应该变换为:YYYY-XXXX
也就是说,你看到产品名单上的编号:(01)1872-8756
其实应该为:(01)8756-1872
怎么办?
别担心,小王用PRXCHANGES()函数, 移形换影把位置就给换了过来。
2. 初识PRXCHANGES()
这个函数有两个作用:
1)任意字符的替换;
2)可以帮我们自由的对一段话进行重新组合,也就是我们本集要解决的问题。
前提是一定要配合PRXPARSE使用。
1)替换
pattern=PRXPARSE(“s/shushuo/shuaishuai/”)
PRXCHANGE(pattern,times, string, new_string, result_length, truncation-value, number_of_changes)
不要看到一大堆参数就觉得复杂,我标灰色的其实一般都用不太到的。
首先PRXPARSE()语句和之前有些不太一样,注意标红色的部分。
正则表达式中开头多了一个s字母,它用来指定进行替换或者重排,在”//”两个斜杠之间,还有一个斜杠/(标注为红色),它表示:斜杠左边为被替换的部分,斜杠右边为替换后的字符,本例中也就是要将“shushuo”替换为“shuaishuai”。
PACHANGE()的参数用法如下:
- pattern就是前面PRXPARSE指定的正则表达式。
- Times用来指定被替换的次数,如果设为-1,则表示只要字符里面有符合的,都进行替换。
- String是要替换的字符,new_string是替换后的新字符串。
- Result_length返回新字符的长度
- Trucation-value返回0或者1,表示新字符是否经过了裁剪,如果新字符长度过长,就会进行裁剪,为1。
- Numer of changes返回原字符中有多少被匹配替换了。
当然,也可以不生成新的字符new_string,只在原字符中进行替换修改,如:
pattern=PRXPARSE(“s/shushuo/shuaishuai/”)
PRXCHANGES(pattern,-1, string)
2)重排
这个有意思了,前面我们说过“打包”,就是把正则表达式的一部分括起来,将这一段“打包”。这里,我们可以将的部分进行重排:
pattern=PRXPARSE(“s/(shu)(shuo)/$2$1/”)
PRXCHANGE(pattern,times, string, new_string, result_length, truncation-value, number_of_changes)
变动主要在PRXPARSE上,将(shu)和(shuo)打包起来,用$1和$2分别表示,后面的顺序$2$1,意思就是按照shuoshu的方式进行排列,我们在SAS上看一下
data temp; string="I love shushuo"; pattern=PRXPARSE("s/(shu)(shuo)/$2$1/"); call PRXCHANGE(pattern, -1, string); fileprint; put string=; run;
输出结果为:
shushuo已经被重排为shuoshu啦!
3. 问题解决
我们先对之前整理好的产品id名单进行重排:
id |
---|
(01)1872-8756 |
(05)9212-0098 |
PD(05)9206-4571 |
(12)6753-5513 |
PD(12)6434-4532 |
(09)1352-3154 |
将-前后的四位数字调换,即1872-8756变成8756-1872等,SAS代码如下:
data production; if _N_=1then pattern=PRXPARSE("s/(P?D?(dd) ?)(d{4})(-)(d{4})/$1$4$3$2/"); retain pattern; input id $char40.; length new_id $40.; call PRXCHANGE(pattern,-1, id, new_id, r_length,trunc,n_of_changes); datalines; (01)1872-8756 (05)9212-0098 PD(05)9206-4571 (12)6753-5513 PD(12)6434-4532 (09)1352-3154 ; procprintnoobs; title'Production ID'; var id new_id; run;
结果为:
我们再尝试一下把这个融入到最初的代码中去,这里给出我自己的代码,供大家参考:
data production; if _N_=1then; pattern=PRXPARSE("s/(P?D?(dd)?)(d{4})(-)(d{4})/$1$4$3$2/"); retain pattern; if _N_=1then pattern2=PRXPARSE("/P?D?(dd) ?d{4}-d{4}/"); retain pattern2; input name $char40.; length new_name $40.; length id $ 20; call PRXCHANGE(pattern,-1,name, new_name); call PRXSUBSTR(pattern2, new_name, start,length); if length gt 0thendo; id=substr(new_name, start, length); id=compress(id," "); output; end; datalines; (01)1872-8756 Body shop P1 Book B13 (05)9212-0098 PD(05)9206-4571 Shushuophone (12)6753-5513 None here PD(12)6434-4532 P&DWashing PC Pro4321S:(09) 1352-3154 ; procprintnoobs; title'Production ID'; var name new_name id; run;
SAS的结果为: