stringr package를 이용한 문자열 조작
2014-07-04
R
stringr package
최근 R for everyone이라는 책을 읽었다. 그 중 stringr 이라는 패키지를 이용한 문자열 처리 방법이 나와 있어 이번 기회에 정리해 보려 한다.
R 표준 base 패키지에 포함된 함수군와 비슷한 기능을 하는 것으로 보이지만 더 합리적인 출력형식을 가지므로 사용하기 편리하다.
이 패키지의 몇몇 특징을 살펴보면
factor와 character를 같은 방식으로 처리
일관성 있는 함수 이름과 인수
- 다른 함수의 입력값으로 사용하기 편리한 출력값.
- 길이 0인 입력값에 대해 길이 0인 결과를 돌려줌
- 입력값
NA
가 포함되어 있을 때는 그 부분의 결과를NA
로 돌려줌
사용빈도가 떨어지는 문자열 조작 처리를 과감하게 제거하여 간략화시킴
Installation
ggplot2를 설치하면 자동으로 설치된다. 혹은
> install.packages("stringr")
함수
Basic string operation
str_length(string)
- 문자열의 길이를 계산.
base::nchar(x)
와 같은 기능을 하는 함수. 단,NA
에 대해서는 2가 아닌NA
를 돌려준다.
> library(stringr) > str_length(c("i", "like", "programming", NA))
#> [1] 1 4 11 NA
> nchar(c("i", "like", "programming", NA))
#> [1] 1 4 11 NA
- 문자열의 길이를 계산.
str_sub(string, start=1, end=-1)
- 문자열을 부분적으로 참조, 변경.
base::substr()
와 같은 기능을 하는 함수. 음수를 사용하여 문자열의 끝으로 부터의 위치를 지정할 수 있다.
> hw <- "Hadley Wickham" > str_sub(hw, 1, 6)
#> [1] "Hadley"
> substr(hw, 1, 6)
#> [1] "Hadley"
> str_sub(hw, end = 6)
#> [1] "Hadley"
> str_sub(hw, -7)
#> [1] "Wickham"
- 문자열을 부분적으로 참조, 변경.
str_c(..., sep='', collapse=NULL)
,str_join(..., sep='', collapse=NULL)
- 문자열을 통합. 디폴트의
sep
가 스페이스 공백이 아니므로base::paste0()
와 비슷하다.
> str_c(letters[-26], " comes before ", letters[-1])
#> [1] "a comes before b" "b comes before c" "c comes before d" #> [4] "d comes before e" "e comes before f" "f comes before g" #> [7] "g comes before h" "h comes before i" "i comes before j" #> [10] "j comes before k" "k comes before l" "l comes before m" #> [13] "m comes before n" "n comes before o" "o comes before p" #> [16] "p comes before q" "q comes before r" "r comes before s" #> [19] "s comes before t" "t comes before u" "u comes before v" #> [22] "v comes before w" "w comes before x" "x comes before y" #> [25] "y comes before z"
> paste0(letters[-26], " comes before ", letters[-1])
#> [1] "a comes before b" "b comes before c" "c comes before d" #> [4] "d comes before e" "e comes before f" "f comes before g" #> [7] "g comes before h" "h comes before i" "i comes before j" #> [10] "j comes before k" "k comes before l" "l comes before m" #> [13] "m comes before n" "n comes before o" "o comes before p" #> [16] "p comes before q" "q comes before r" "r comes before s" #> [19] "s comes before t" "t comes before u" "u comes before v" #> [22] "v comes before w" "w comes before x" "x comes before y" #> [25] "y comes before z"
> str_c(letters, collapse = ", ")
#> [1] "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z"
- 문자열을 통합. 디폴트의
str_split(string, pattern, n=Inf)
- 문자열을 분리.
base::strsplit(x, split)
와 대응하는 함수. 최대 n 개의 분할을 지정할 수 있다. 결과값은 list. 문자열을 정해진 n 개로 나누는str_split_fixed()
도 있다. 결과값은 matrix.
> fruits <- c( + "apples and oranges and pears and bananas", + "pineapples and mangos and guavas" + ) > str_split(fruits, " and ")
#> [[1]] #> [1] "apples" "oranges" "pears" "bananas" #> #> [[2]] #> [1] "pineapples" "mangos" "guavas"
> strsplit(fruits, "and")
#> [[1]] #> [1] "apples " " oranges " " pears " " bananas" #> #> [[2]] #> [1] "pineapples " " mangos " " guavas"
> str_split(fruits, " and ", n = 3)
#> [[1]] #> [1] "apples" "oranges" "pears and bananas" #> #> [[2]] #> [1] "pineapples" "mangos" "guavas"
> str_split(fruits, " and ", n = 2)
#> [[1]] #> [1] "apples" "oranges and pears and bananas" #> #> [[2]] #> [1] "pineapples" "mangos and guavas"
> str_split_fixed(fruits, " and ", 4)
#> [,1] [,2] [,3] [,4] #> [1,] "apples" "oranges" "pears" "bananas" #> [2,] "pineapples" "mangos" "guavas" ""
- 문자열을 분리.
Pattern Matching
str_detect(string, pattern)
- 매치하는 곳이 있는지 없는지를 logical 값으로 돌려준다.
base::grepl(pattern, x)
과 대응.
> fruit <- c("apple", "banana", "pear", "pinapple") > str_detect(fruit, "a")
#> [1] TRUE TRUE TRUE TRUE
> str_detect(fruit, "^a")
#> [1] TRUE FALSE FALSE FALSE
> str_detect(fruit, "a$")
#> [1] FALSE TRUE FALSE FALSE
> str_detect(fruit, "b")
#> [1] FALSE TRUE FALSE FALSE
> str_detect(fruit, "[aeiou]")
#> [1] TRUE TRUE TRUE TRUE
- 매치하는 곳이 있는지 없는지를 logical 값으로 돌려준다.
str_count(string, pattern)
- 매치하는 곳의 수를 돌려준다.
> str_count(fruit, c("a", "b", "p", "p"))
#> [1] 1 1 1 3
str_locate(string, pattern)
- 처음으로 매치되는 곳의 start, end 위치를 행렬로 돌려준다.
> str_locate(fruit, "e")
#> start end #> [1,] 5 5 #> [2,] NA NA #> [3,] 2 2 #> [4,] 8 8
str_extract(string, pattern)
,str_extract_all(string, pattern)
- 매치된 부분 문자열을 추출. 매치되지 않은 요소는
NA
.base::grep(pattern, x, value=TRUE)
는 매치된 요소만 원래의 형태로 돌려준다.
> shopping_list <- c("apples x4", "flour", "sugar", "milk x2") > str_extract(shopping_list, "\\d")
#> [1] "4" NA NA "2"
> grep("\\d", shopping_list, value = TRUE)
#> [1] "apples x4" "milk x2"
> str_extract(shopping_list, "[a-z]+")
#> [1] "apples" "flour" "sugar" "milk"
> grep("[a-z]+", shopping_list, value = TRUE)
#> [1] "apples x4" "flour" "sugar" "milk x2"
- 매치된 부분 문자열을 추출. 매치되지 않은 요소는
str_match(string, pattern)
,str_match_all(string, pattern)
- 매치된 부분 문자열을 추출하고 참조를 행렬로 돌려준다。
str_extract(string, pattern)
의 결과를 1열에 각 괄호에 매치된 이후의 결과가 2열 이후에 들어간다. 예제를 보는 것이 이해에 도움이 됨.
> strings <- c(" 219 733 8965", "329-293-8753 ", "banana", "595 794 7569", + "387 287 6718", "apple", "233.398.9187 ", "482 952 3315", + "239 923 8115", "842 566 4692", "Work: 579-499-7527", "$1000", + "Home: 543.355.3679") > phone <- "([2-9][0-9]{2})[- .]([0-9]{3})[- .]([0-9]{4})" > > str_extract(strings, phone)
#> [1] "219 733 8965" "329-293-8753" NA "595 794 7569" #> [5] "387 287 6718" NA "233.398.9187" "482 952 3315" #> [9] "239 923 8115" "842 566 4692" "579-499-7527" NA #> [13] "543.355.3679"
> str_match(strings, phone)
#> [,1] [,2] [,3] [,4] #> [1,] "219 733 8965" "219" "733" "8965" #> [2,] "329-293-8753" "329" "293" "8753" #> [3,] NA NA NA NA #> [4,] "595 794 7569" "595" "794" "7569" #> [5,] "387 287 6718" "387" "287" "6718" #> [6,] NA NA NA NA #> [7,] "233.398.9187" "233" "398" "9187" #> [8,] "482 952 3315" "482" "952" "3315" #> [9,] "239 923 8115" "239" "923" "8115" #> [10,] "842 566 4692" "842" "566" "4692" #> [11,] "579-499-7527" "579" "499" "7527" #> [12,] NA NA NA NA #> [13,] "543.355.3679" "543" "355" "3679"
- 매치된 부분 문자열을 추출하고 참조를 행렬로 돌려준다。
str_replace(string, pattern, replacement)
- 매치되지 않은 부분은 그대로 매치된 부분만 치환.
base::sub(pattern, replacement, x)
와 대응.base::gsub()
과 같이 모든 매치부분을 치환하기 위해서는str_replace_all()
을 사용.
> fruits <- c("one apple", "two pears", "three bananas") > str_replace(fruits, "[aeiou]", "-")
#> [1] "-ne apple" "tw- pears" "thr-e bananas"
> str_replace_all(fruits, "[aeiou]", "-")
#> [1] "-n- -ppl-" "tw- p--rs" "thr-- b-n-n-s"
위에서 나열한 함수에서 _pattern_은 디폴트로 POSIX 정규표현식으로 취급된다. 이하의 함수를 통해 인수값을 변경할 수 있다.
- 매치되지 않은 부분은 그대로 매치된 부분만 치환.
stringr::fixed(string)
- 입력값 그대로의 문자로 매칭 시킴
stringr::ignore.case(string)
- 대문자 소문자를 무시하여 매치 시킴
stringr::perl(string)
- Perl 정규표현식으로 취급
Formatting
str_trim(string, side="both")
- 공백문자를 제거.
str_pad(string, width, side="left", pad=" ")
- 폭을 width 만큼 늘려서 side를 기준으로 공백을 pad에 지정된 문자로 채워넣음.
str_wrap(string, width=80, indent=0, exdent=0)
- 지정한 폭으로 줄바꿈. indent는 선두행의 왼쪽 여백, exdent는 그 이외 행의 왼쪽여백.
결국은 정규표현식을 잘써야 한다는 이야기!!