Fw: [筆記] R的字串處理

看板R_Language作者 (Logit(odds))時間11年前 (2013/03/30 20:33), 9年前編輯推噓3(300)
留言3則, 3人參與, 最新討論串1/2 (看更多)
※ [本文轉錄自 Statistics 看板 #1CA5vrBC ] 作者: 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

06/28 16:40, , 1F
as.character 這個忘記了吧XD
06/28 16:40, 1F
※ 編輯: gsuper 來自: 140.113.239.247 (06/28 16:46)

06/28 17:37, , 2F
之前看到的, 把字串當code 執行:
06/28 17:37, 2F

06/28 17:37, , 3F
eval(parse(text = 字串物件))
06/28 17:37, 3F

06/29 12:32, , 4F
nchar
06/29 12:32, 4F

06/29 12:32, , 5F
match
06/29 12:32, 5F

06/29 12:33, , 6F
expression
06/29 12:33, 6F

06/29 12:33, , 7F
parse
06/29 12:33, 7F

06/29 12:34, , 8F
regression expression可用在很多function.
06/29 12:34, 8F

06/29 12:34, , 9F
google:龍門少尉的窩
06/29 12:34, 9F

06/29 12:35, , 10F
Chambers(2008)"Software for Data Analysis:
06/29 12:35, 10F

06/29 12:35, , 11F
Progamming with R", Springer-Verlag.
06/29 12:35, 11F
※ 編輯: 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) ※ 發信站: 批踢踢實業坊(ptt.cc) ※ 轉錄者: gsuper (140.113.239.247), 時間: 03/30/2013 20:33:05

03/30 23:35, , 12F
已收錄至精華區
03/30 23:35, 12F

04/05 15:03, , 13F
推這篇 很實用!
04/05 15:03, 13F

12/11 17:04, , 14F
12/11 17:04, 14F
※ 編輯: gsuper (114.32.201.238), 04/30/2015 15:31:22
文章代碼(AID): #1HLjk2HI (R_Language)
討論串 (同標題文章)
以下文章回應了本文
完整討論串 (本文為第 1 之 2 篇):
文章代碼(AID): #1HLjk2HI (R_Language)