4. call PRXPOSN() | 撕数据!

2018-04-04 16:52:41 浏览数 (1)

【SAS Says·扩展篇】撕数据! | 4. call PRXPOSN()

0. 前集回顾

1. 新的问题

2. 初识 PRXPOSN()

3. 问题解决


0. 前集回顾:

小王刚刚毕业,来到数说国际零售公司任数据分析师,产品部的妹子求助他,希望可以帮忙做这么一件事:下面是一份产品名单,有的行是产品的名字,有的行是产品的编号,现在只想将编号保留下来(即红色字体的部分),尤其是最后一行,这一行只要一部分。

(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

小王写了一段代码,很快就搞定了:

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); if length GT 0thendo; id=substr(name,start,length); output; end; keep id; 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 id; run;

输出结果为:

这个问题真是圆满的解决了。

点击这里回顾:

  • 提取文本数据,分析师小王初上手!
  • 正则表达式的“阿赖耶识”
  • 庖丁解牛切割数据!

1. 新的问题

不错,一个新的问题来了,

”括号里面的数字代表了产品的类别,能不能将它单独提出来?“

当然,你可以在目前的表的基础上,用excel处理,比如:

If 第一个字符是”(” then 提取后面两个数字

If 第一个字符是”P” then 提取后面第四、第五个数字

当然这也一点都不酷,而且如果名单的后面有其他变动,比如前面的PD被错拼成BD了、或者真有一个前缀是BD呢?

还是用正则表达式一次性搞定吧!这就要引出我们今天的主角——PRXSON!

2. 初识PRXPOSN()

这个语句要配合PAXMATCH(或其他PRX搜索函数)使用。需要三步:

在正则表达式中,用括号()将需要提取的一小部分括起来,我自己称之为“打包”,比如,在产品编号的例子中,我们需要打包括号里的两位数字,那么我们就在正则表达式中将这两个dd括起来:

“/P?D?((dd)) ?d{4}-d{4}/”

并放入pattern中:

Pattern=PRXPARSE(“/P?D?((dd)) ?d{4}-d{4}/”)

用PRXMATCH匹配这段正则表达式

PAXMATCH(pattern,name)

用PRXPOSN函数得到产品编号(就是括号里,我们要提取的那个)的起始位置和长度。

CALLPRXPOSN(pattern, 1, start, length)

重点来了,PRXPOSN的格式为:

Call PRXPOSN(pattern-id, 区块编号, start, length)

这里pattern-id是正则表达式,区块编号就是正则表达式中,我们打包起来的。只打包一个,那么编号就是1,打包两个,那么可以选择1或者2。

然后,这个函数就把区块的起始位置和长度赋给了start和length。

用substr()函数将区块抓下来

本例中,产品类型就是:

Category=Substr(name,start, length)

3. 问题解决

好了,现在来看一下本例中代码要怎么写:

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, 1, start_1, length_1); category=substr(name, start_1, length_1); output; end; keep id category; 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 id category; run;

最后的结果为:

趁热,咱们再加一列吧,标识出哪些产品是过期的,即PD。

直接上代码,非常简单,大家自己研究研究吧:

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;

结果为:


0 人点赞