移形换影 | 【SAS Says · 扩展篇】

2018-04-08 11:51:09 浏览数 (1)

【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的结果为:


0 人点赞