全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 SAS专版
7189 11
2013-06-18
如何读取不等长度不等数量带分隔符字符串?比如有如下字符数据
复制代码
现要统计各词“ASUS”、“IBM”等出现频率,怎样实现?

一般来说我们的思路是各行数据中所有的词读入到同一变量中,怎么实现你,上网查找,找到一台湾网友的解决方法,现在分享给大家,欢迎用其它解决方法,请分享在此。

二维码

扫码加我 拉你入群

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

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

全部回复
2013-6-18 23:29:07

上网查找,发现一台湾网友的解决方案,方法如下:



解开字符串内的逗点区隔文字
http://r97846001.blog.ntu.edu.tw/2011/08/27/pull-all-words-from-string/

有接触数据的捧由,应该有看过一种coding方式是将数值/文字链接在同一个字段中,例如一位研究员将一位个案在五次不同时间测量的血压值输入到excel档案中

128,130,122,140,126

在实际纳入分析时,比方说计算五次血压平均

这字段总得要解开成为五列数值吧!

参考过SAS help后,以下说明将以这串品牌名称作范例

分享作法一给各位,如果有其他方法也欢迎提供讨论

string=ASUS,CORSAIR,GIGABYTE,MSI,ACER,BlackBerry,intel,Shuttle

目标是将该字符串依照逗号解开成为8个rows

关于字符串处理的函数,用力回想后跑出了:SCAN、COMPRESS、FIND、CAT等相关函数

其中,扫描一个字符串、指定位置后并且输出的功能,非SCAN莫属

SCAN函数范例:string=’ABC.DEF(X=Y)’;  word=scan(string, 3); 执行后的word值为X=Y

但是,SCAN还不足以解决现在的问题

因为需要逗点分隔之间的所有单字,没错吧!

介绍一个CALL ROUTINE的函数:CALL SCAN

CALL SCAN(string, n, position, length, <delimiters>);

  • string: 通常是一个变项名称, 例如上面的string
  • n: 数字, 该字符串内用户希望撷取出多少字词(word), n为正数表示左到右扫, 负数表示从右到左扫, |n|大于string内的字词数则回传零
  • position: 回传该字词所在起始位置
  • length: 回传该字词的长度
  • <delimiters>: 选择性的option, 可接受空白, < ( + & ! $ * ) ; ^ – / , % |等做为区隔符号

注意:使用CALL SCAN后要取得字词,需要使用SUBSTRN函数

而SUTSTRN利用CALL SCAN得到的字词起始位置与长度再做撷取动作,并非CALL SCAN完成整个目标喔!

这个范例应用到DO LOOP的概念来做重复扫字词的动作

巧妙搭配output完成字词输出


data test;
      input id $ string $60.;/*由于字符串很长, 指定长度$60,$表示的意思应该..不陌生吧, 表示非数值*/
      drop string;
      do i=1 to 99;/*由于要让他输出每次扫到的字词, 随意订个99~在此可以完整扫出*/
     call scan ( string, i, position , length , "," );/*以逗点做区隔符号, 由左至右启动*/
           if not position then leave;/*若没有扫到位置,即跳出*/
          name=substrn ( string ,  position ,   length );/*将个别的字词放到变项name里*/
         output;/*在此马上输出字词结果*/
   end;/*有do就有end, 请不要忘记*/
datalines;
001 ASUS,CORSAIR,GIGABYTE,MSI,ACER,BlackBerry,intel,Shuttle
002 IBM,Lenovo
003 GIGABYTE,MSI,ACER,DELL
;
proc print data=test;/*在output窗口输出结果*/
run;
proc freq data=test;
table name;
run;



延伸函数:CALL SCANQ (最大的差别是此函数不考虑区隔符号)





二维码

扫码加我 拉你入群

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

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

2013-6-18 23:42:18
同求啊,为国产主义服务
二维码

扫码加我 拉你入群

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

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

2013-6-19 11:38:30
countc+scan函数也可以很好的解决
data test;
input id $ string $60.;/*由于字符串很长, 指定长度$60,$表示的意思应该..不陌生吧, 表示非数值*/
        length=countc(string,",")+1;
        do i=1 to length;
                new_name=scan(string,i,",");
                output;
        end;
        keep id new_name;
datalines;
001 ASUS,CORSAIR,GIGABYTE,MSI,ACER,BlackBerry,intel,Shuttle
002 IBM,Lenovo
003 GIGABYTE,MSI,ACER,DELL
;
run;
二维码

扫码加我 拉你入群

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

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

2013-6-19 21:15:30
可~乐 发表于 2013-6-19 11:38
countc+scan函数也可以很好的解决
data test;
input id $ string $60.;/*由于字符串很长, 指定长度$60,$表 ...
不错,还有无其它方法吗?
二维码

扫码加我 拉你入群

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

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

2013-6-19 22:06:54
做一点小小的该动,可以不用调整循环次数。

data test;
      input id $ string $60.;
      drop string n i position length;
      i = 1;
  do until (n=0);
     call scan ( string, i, position , length , "," );
       if not position then n=0;
      else     name=substrn ( string ,  position ,   length );
         output;
          i+1;
   end;
datalines;
001 ASUS,CORSAIR,GIGABYTE,MSI,ACER,BlackBerry,intel,Shuttle
002 IBM,Lenovo
003 GIGABYTE,MSI,ACER,DELL
;
二维码

扫码加我 拉你入群

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

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

点击查看更多内容…
相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群