作者gsuper (统计的巴比伦塔)
看板Statistics
标题[程式] R的字串处理
时间Mon Jun 28 16:33:54 2010
[软体程式类别]:
R
[程式问题]:
资料处理
[软体熟悉度]:
中(3个月到1年)
[问题叙述]:
最近常在处理字串
发现自己会的 function 很不够用
想多学点 function
我列出一些我常用的
希望能抛砖引玉
请各位高手能教我一些高招
[程式范例]:
前言 :
R 的字串处理 ,
要小心注意 character , factor , numeric 这三种物件的误转换和混用
factor 是一种很讨厌的物件 ,
因为它在转成数字和字串的时候 ,
常常会变成跟原本不一样的东西 ,
建议资料处理的过程 ,
预设用 matrix 和 character 两种而避免使用 data.frame
------------------------------------------------------------------
1.字串黏合
paste ("A","B",sep="") ---->>> "AB"
2.字串切割
strsplit("A.B",split=".",fixed=T) ---->>> "A" "B"
3.精确稳合
x <- c("AB","AA")
x %in% "AB" ---->>> TRUE FALSE
4.部份吻合 + (回传 which)
x <- c("AB","AA")
grep("B",x) ---->>> 1
grep("A",x) ---->>> 1 2
grep("B",x,value=T) ---->>> "AB"
grep("B",x,value=T,invert=T) ---->>> "AA"
grep("C",x) ---->>> integer(0)
#若目的是要找 index , 建议改用 grepl
4-2.部份吻合 + (回传判断式)
x <- c("AB","AA")
grepl("B",x) ---->>> TRUE FALSE
4-3.部份吻合 + (回传位置) + (回传??)
x <- c("BBB","AAA","CCB")
regexpr("B",x) ---->>> 1 -1 3 (第一次 "hit" 的位置)
1 -1 1 (有无 "hit")
5.子字串
substr("human123456",start=1,stop=5) ---->>> "human"
!!注意!! 4-3 的 regexpr
与这个 substr 结合起来 ,
在写 网页Parser 的时候很好用
regexpr 能定义出 statr=多少
所谓的网页Parser
就是你去下载某些 html 档案
检视原始码
然後找出你需要的资料
再找出一些能 cut 的规则
用 strsplit 搭配 TR , TD 之类的字串去切出你要的资料
6.特定字元取代 (1st hit)
x <- "AABB"
sub("A",replacement="C",x) ---->>> "CABB"
6-2.全部特定字元取代 (global hit)
x <- "AABB"
gsub("A",replacement="C",x) ---->>> "CCBB"
7.计算字串长度
### 尽量别用这个 fuction
x <- c("A","AAA","AAAAA")
nchar(x) ---->>> 1 3 5
nchar(as.factor(x)) ---->>> 1 1 1
8.多重字元(串)贴合 (矩阵内)
x <- matrix(letters[1:6],2,3)
apply(x,1,paste,collapse="") ---->>> "ace","bdf"
apply(x,2,paste,collapse="") ---->>> "abc","def"
9. 字元反转
x <- c("A B","*.")
sapply(lapply(strsplit(as.character(x), NULL), rev), paste, collapse="")
[1] "B A" ".*"
10.字元检查
x <- c("A B","*.")
unique(unlist(strsplit(as.character(x),split="",fixed=T)))
[1] "A" " " "B" "*" "."
-----------------------------------------------------------
Regular expression : 字串模糊比对 , 或特定字母排列模式的抓取
在R内
基本上分成3种
Basic regular expression (BRE) --> extended = FALSE
Extended regularexpression (ERE) --> extended = TRUE (预设)
perl-like (perl) --> perl = TRUE
双冒号代表我测试过且成功
单冒号代表网路上抓下来或是测试失败
--------------------------------------------------------------
通用部分
{,}
* :: {0, } 至少出现0次, 最多无限多次
+ :: {1, } 1 无限多次
? :: {0,1} 0 1
[Aa] :: A 或 a
[^1-9] :: not 1:9
[1-9] :: 1:9
[a-z] :: a b c ... z
[A-Z] :: A B C ... Z
[a-zA-Z] :: 所有英文字母
[W-z] :: WXYZabc....z
[w-Z] :: 不可使用!
(AB) :: 括号一次收集多个字元 ### 一种延伸字串的写法
举例 :
x <- c("company","companies",)
可以用以下两种写法
1. grep("[company|companies]",x)
2. grep("compan(y|ies)",x)
第二种在大资料的时候会比较快
$ :: 字尾限定
^ :: 字首限定
| :: "ABC|EFG" --> grep("ABC"or"DEF",x)
. :: 任意字元
-----------------------------------------------------
ERE , extended = TRUE
digit (数字)
\\d :: [0-9]
\\D :: [^0-9]
[[:digit:]] :: 同上
[^[:digit:]] :: 同上
blank (空白)
\\s :: 能切开 " " 或 "\t"
\\S :: 切开非空白及 tab 的字元
[[:blank:]] :: 同上
[^[:blank:]] :: 同上
AlphaBet + Digit (正常字元)
\\w :: [0-9a-zA-Z]
\\W :: [^0-9a-zA-Z]
[[:alnum:]] :: 同上
[^[:alnum:]] :: 同上
AlphaBet (英文字元)
[[:alpha:]] :: 同上
[^[:alpha:]] :: 同上
特殊符号
[[:punct:]] :: ! " # $ % & ' ( ) * + , - .
/ : ; < = > ? @ [
\ ] ^ _ ` { | } ~
[^[:punct:]] :: 英文字 , 数字 (注意! , \t 和 \n 都会被切掉)
注意 ! 正斜线这个符号很容易与其他 regular expr 混淆
必须仔细检查 "
\" 存在的字串
可印符号
[[:print]] :: 所有字元 (数字,字母,特殊符号,空白)
\n , \t , \001 除外
16进位字元
[[:xdigit:]] :: 16进位有关英文或数字
[0-9a-fA-F]
大小写英文字元
[[:upper:]] :: 大写英文字元 [A-Z]
[^[:upper:]] :: 非大写 [^A-Z]
[[:lower:]] :: 小写 [a-z]
[^[:lower:]] :: ^[a-z]
注意 "\t" 还是会被留下来
空白和换行等
[[:space:]] :: " " , \t , \n , \f , \r
(\f : 换行但不回到行头)
(\r : 回到行头并消除此行内所有的文字)
P.S. 这两种不常用,当豆知识即可
[[:graph:]] :: [A-Za-z0-9]再加[["punct"]]
----------------------------------------------------------
perl = TRUE
\\w : [A-Za-z0-9_]
\\W : [^A-Za-z0-9_]
\\s : [\t\n\r\f]
\\S : [^\t\n\r\f]
\\d : [0-9]
\\D : [^0-9]
----------------------------------------------------------
regular expression 工事中 (未完)
感觉这篇被我当笔记来用了
reference:
1.
http://www.rtfiber.com.tw/~changyj/
2.
http://www.stat.psu.edu/~dhunter/R/html/base/html/regex.html
----------------------------------------------------------
大小写切换
TRUTH <- c("Abc","ABC")
a <- gsub("(\\w)","\\L\\1",TRUTH,perl=TRUE) ---> "abc","abc"
b <- gsub("^(\\w)","\\U\\1",a,perl=TRUE) ---> "Abc","Abc"
同上 , 非常神秘的 Bug !?
T123 <- c("Tgfbr1","Cd320","Ndrg3","Aldoa","Bckdk","Tmed3","Hfe2")
> gsub( "(\\w)", "\\L\\1" , T123 , perl=T)
[1] "LTLgLfLbLrL1" "LCLdL3L2L0" "LNLdLrLgL3"
[4] "LALlLdLoLa" "LBLcLkLdLk" "LTLmLeLdL3"
[7] "LHLfLeL2"
> gsub( "(\\w)", "\\L\\1" , T123 , perl=TRUE)
[1] "tgfbr1" "cd320" "ndrg3" "aldoa" "bckdk" "tmed3"
[7] "hfe2"
---------------------------------------
消除多余空白
> x <- "Hey! Apple "
> gsub(" {2,}","",x)
[1] "Hey! Apple" ### 容忍一个空白 , 但两个以上至无限大则消除
---------------------------------------
在处理混合字串与数字的资料矩阵的时候
常常需要在 data.frame 和 matrix 之间切换
有时候会字串会被一些预设的空白字元夹住
ex:
"1" , "15" , "333"
经过转换以後
" 1" , " 15" , "333" (fit 最长字串的长度)
> DATA <- gsub("^ *| *$",as.matrix(DATA))
---------------------------------------
### 一些参考的 pattern
1. "^\\d+$" ### 纯数字的栏位 ###
2. "^ *| *$" ### 字首字尾的空白(搭配 gsub) ###
3. "^[0][\\.]{0,1}[0]*$" ### "0" "0.0" "0.00" "0.000" "0.0000" ,
bug 是 "0." "00"
####################################################################
放一些 linux 下的好用指令
光用 R 来做字串处理不够用
原因在於若处理的档案太大
光是读进 R 就累死人
这边主要是应用在档案减肥
文字档案
rs123\t0|1:0000\tAAAA
rs456\t1|0:0000\tBBBB
###################
横向
grep [-w : word]
[-f : 给 pattern file]
[-F : 精确比对] ### 若要搜寻固定字串 , -F必下 (快超多)
1. cat 文字档案|grep -w 'rs' ### 没东西
2. cat 文字档案|grep -w -F 'rs123' ### 出第一行
3. car 文字档案|grep -w '^rs.*$' ### 二行皆出
###################
纵向
cut [-d : 用tab切开会是3个column的矩阵]
1. cut -d'\t' -f1,2 原档 > 新档 ### 留下 1 and 2 columns
###################
横向
sed
1. sed -n '6,$p' 原档 > 新档 ### 从第六行开始 , print 至尾行
### 或可理解成, 把 1~5行切掉
2. sed 's/
:\S*/
HAHA/g' 原档 > 新档 ### s=取代 , g=global
### 把红色的正规 pattern 取代成绿色
###################
当档案有 10000000 rows , 读不进 R 怎办?
就算读进 R , 资料太大一直 SWAP 电脑动不了怎麽办?
经过一番苦战
我建议以下的思考方式
0. 先透过上述方式
直接在终端机把档案减肥
1. 档案列数 <- system("wc -l 档案",intern=TRUE)
LOOP <- ceiling(档案列数 / 5000)
for(g in 1:LOOP) ### 用while可省前两行
{ tmp <- read.table(档案,
skip=5000*(g-1),
nrow=5000) ### 但我只熟 for
expr(中间的各种处理)
write.table(tmp,g)
Sys.sleep(5) ### 给一点时间让电脑回气
}
2. system(
"cat 小档案1 小档案2 小档案3 .... > 总档案") ### 档案 rbind()
虽然不是最快的方法
但 Over night 是一定可以把档案处理完的
以上
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.113.239.247
1F:→ lin15:as.character 这个忘记了吧XD 06/28 16:40
※ 编辑: gsuper 来自: 140.113.239.247 (06/28 16:46)
2F:推 Wush978:之前看到的, 把字串当code 执行: 06/28 17:37
3F:→ Wush978:eval(parse(text = 字串物件)) 06/28 17:37
4F:→ clickhere:nchar 06/29 12:32
5F:→ clickhere:match 06/29 12:32
6F:→ clickhere:expression 06/29 12:33
7F:→ clickhere:parse 06/29 12:33
8F:→ clickhere:regression expression可用在很多function. 06/29 12:34
9F:→ clickhere:google:龙门少尉的窝 06/29 12:34
10F:→ clickhere:Chambers(2008)"Software for Data Analysis: 06/29 12:35
11F:→ clickhere:Progamming with R", Springer-Verlag. 06/29 12:35
※ 编辑: gsuper 来自: 140.113.239.247 (07/02 22:14)
※ 编辑: gsuper 来自: 140.113.239.247 (07/02 22:21)
※ 编辑: gsuper 来自: 140.113.239.247 (07/02 22:22)
※ 编辑: gsuper 来自: 140.113.239.247 (07/02 22:48)
※ 编辑: gsuper 来自: 140.113.239.247 (07/02 23:12)
※ 编辑: gsuper 来自: 140.113.239.247 (07/02 23:30)
※ 编辑: gsuper 来自: 140.113.177.3 (07/03 01:41)
※ 编辑: gsuper 来自: 140.113.177.3 (07/03 03:12)
※ 编辑: gsuper 来自: 140.113.239.247 (07/03 21:39)
※ 编辑: gsuper 来自: 140.113.239.247 (07/08 10:32)
※ 编辑: gsuper 来自: 140.113.239.247 (07/08 17:19)
※ 编辑: gsuper 来自: 140.113.239.247 (07/08 17:28)
※ 编辑: gsuper 来自: 140.113.239.247 (08/03 22:45)
※ 编辑: gsuper 来自: 140.113.239.247 (08/03 22:47)
※ 编辑: gsuper 来自: 140.113.239.247 (09/03 21:49)
※ 编辑: gsuper 来自: 140.113.239.247 (09/03 21:55)
※ 编辑: gsuper 来自: 140.113.239.247 (09/03 22:02)
※ 编辑: gsuper 来自: 140.113.239.247 (09/03 22:03)
※ 编辑: gsuper 来自: 140.113.239.247 (09/03 22:19)
※ 编辑: gsuper 来自: 140.113.239.247 (09/03 23:10)
※ 编辑: gsuper 来自: 140.113.239.247 (09/03 23:35)
※ 编辑: gsuper 来自: 140.113.239.247 (09/03 23:44)
※ 编辑: gsuper 来自: 140.113.239.247 (09/21 22:26)
※ 编辑: gsuper 来自: 140.113.239.247 (09/21 22:54)
※ 编辑: gsuper 来自: 140.113.239.247 (09/29 13:26)
※ 编辑: gsuper 来自: 140.113.239.247 (10/04 13:54)
※ 编辑: gsuper 来自: 140.113.239.247 (10/04 14:02)
※ 编辑: gsuper 来自: 140.113.239.247 (12/03 17:13)
※ 编辑: gsuper 来自: 140.113.56.120 (12/21 02:15)
※ 编辑: gsuper 来自: 140.113.56.120 (12/29 03:27)
※ 编辑: gsuper 来自: 140.113.56.120 (12/29 03:28)
※ 编辑: gsuper 来自: 140.113.239.247 (02/17 16:33)
※ 编辑: gsuper 来自: 140.113.239.247 (02/21 12:43)
※ 编辑: gsuper 来自: 140.113.239.247 (06/12 19:52)
※ 编辑: gsuper 来自: 140.113.239.247 (06/12 19:52)
※ 编辑: gsuper 来自: 140.113.239.247 (11/09 14:28)
※ 编辑: gsuper 来自: 140.113.239.247 (11/09 14:32)
※ 编辑: gsuper 来自: 140.113.239.247 (11/09 18:58)
※ 编辑: gsuper 来自: 140.113.239.247 (11/09 19:03)
※ gsuper:转录至看板 R_Language 03/30 20:33
12F:推 kimigogo:感谢分享 11/30 18:04
13F:推 jackbook: 推 10/01 11:22