10.2 문자열 기초

작은따옴표나 큰따옴표로 문자열을 생성할 수 있다. 다른 언어와는 달리 두 동작에 차이가 없다. 여러 개의 " 를 포함하는 문자열을 생성하려는 것이 아니라면 항상 " 를 사용할 것을 추천한다.

string1 <- "문자열입니다"
string2 <- '문자열 내에 "인용문"이 포함된 경우, 나는 작은 따옴표를 사용한다'

따옴표 닫는 것을 잊어 버린 경우, 연속문자(continuation character)인 + 가 나타난다.

> "닫는 따옴표가 없는 문자열이다
+    
+    
+ 도와줘요 갇혔어요

이 같은 일이 발생했다면 이스케이프키를 누르고 다시 시도하라!

작은따옴표 문자나 큰따옴표 문자를 문자열에 포함하려면 ‘벗어나기 (escape)’ 위해 \ (이스케이프 키)를 사용할 수 있다.

double_quote <- "\"" # or '"'
double_quote
## [1] "\""
single_quote <- '\'' # or "'"
single_quote
## [1] "'"

같은 원리로 역슬래시 문자를 포함하려면 "\\" 과 같이 두 번 입력해야 한다.

문자열의 출력 표시는 문자열 자체와 같지 않다는 것에 주의하라. 출력에선 이스케이프가 보이기 때문이다. 문자열의 원시 형태를 보려면 writeLines() 를 사용하라.

x <- c("\"", "\\")
x
## [1] "\"" "\\"
writeLines(x)
## "
## \

이 외의 특수 문자들도 매우 많다. 줄바꿈, "\n" , 탭, "\t" 은 가장 일반적인 것들이다. ?'"' , 혹은 ?"'" 로 볼 수 있는 도움말을 통해 전체 목록을 볼 수 있다. 또한 "\u00b5" 과 같은 문자열을 간혹 볼 수도 있는데, 이는 비영어 문자를 모든 플랫폼에서 동작하도록 작성한 것이다.

x <- "\u00b5"
x
## [1] "μ"

복수의 문자열은 종종 c() 로 만들 수 있는 문자형 벡터에 저장된다.

c("one", "two", "three")
## [1] "one"   "two"   "three"

10.2.1 문자열 길이

베이스 R에는 문자열에 동작하는 함수가 많이 있지만 일관성이 없고, 또 따라서 기억해내기 어렵기 때문에 여기에서는 사용하지 않을 것이다. 대신 우리는 stringr 의 함수를 사용할 것이다. 이 함수들의 이름은 좀 더 직관적이며 모두 str_ 로 시작한다. 예를 들어 str_length() 는 문자열의 문자 개수를 알려준다.

str_length(c("a", "R for data science", NA))
## [1]  1 18 NA

공통된 str_ 접두사는 RStudio 이용자에게 특히 유용하다. str_ 을 타이핑하면 자동완성을 불러와서 모든 stringr 함수를 볼 수 있기 때문이다.

img

10.2.2 문자열 결합

문자열을 두 개 이상 결합하기 위해서는 str_c() 를 사용하라.

str_c("x", "y")
## [1] "xy"
str_c("x", "y", "z")
## [1] "xyz"

구분 방식을 컨트롤하기 위해 sep = 인수를 사용하라.

str_c("x", "y", sep = ", ")
## [1] "x, y"
#> [1] "x, y"

대부분의 R 함수들에서 그렇듯 결측값은 설정된 것이 이후로 계속 파급된다(contagious). 결측값을 "NA" 로 출력되길 원하면 str_replace_na() 를 사용하라.

x <- c("abc", NA)
str_c("|-", x, "-|")
## [1] "|-abc-|" NA
str_c("|-", str_replace_na(x), "-|")
## [1] "|-abc-|" "|-NA-|"

앞의 코드에서 본 것처럼 str_c() 는 벡터화되고 짧은 벡터가 긴 벡터와 길이가 같도록 자동으로 재사용한다.

str_c("prefix-", c("a", "b", "c"), "-suffix")
## [1] "prefix-a-suffix" "prefix-b-suffix" "prefix-c-suffix"

길이가 0인 객체는 조용히 삭제된다. 이 특성은 if 와 함께 쓰면 특히 유용하다.

name <- "Hadley"
time_of_day <- "morning"
birthday <- FALSE

str_c(
  "Good ", time_of_day, " ", name,
  if (birthday) " and HAPPY BIRTHDAY",
  "."
)
## [1] "Good morning Hadley."

문자열 벡터를 하나의 문자열로 합치려면 collapse 를 사용하라.

str_c(c("x", "y", "z"), collapse = ", ")
## [1] "x, y, z"

10.2.3 문자열 서브셋하기

문자열의 일부는 str_sub() 를 사용하여 추출할 수 있다. 이 함수는 문자열과 더불어 부분문자열의 위치를 지정하는 startend 인수를 취한다.

x <- c("Apple", "Banana", "Pear")
str_sub(x, 1, 3)
## [1] "App" "Ban" "Pea"
# 음수는 끝에서부터 반대 방향으로 센다
str_sub(x, -3, -1)
## [1] "ple" "ana" "ear"

str_sub() 는 문자열이 너무 짧은 경우에도 오류가 발생하지 않고 가능한 만큼 반환한다는 것을 주목하라.

str_sub("a", 1, 5)
## [1] "a"

str_sub() 의 할당 형식을 사용하여 문자열을 수정할 수도 있다.

str_sub(x, 1, 1) <- str_to_lower(str_sub(x, 1, 1))
x
## [1] "apple"  "banana" "pear"

10.2.4 로케일

앞서 str_to_lower() 를 사용하여 텍스트를 소문자로 변경했다. str_to_upper() 또는 str_to_title() 을 사용할 수도 있다. 그러나 각각의 언어는 대소문자 규칙이 다르므로 대소문자 변경은 생각보다 더 복잡하다. 로케일을 지정하여, 어떤 규칙 집합을 사용할지 정할 수 있다.

# 터키어는 i가 점이 있는 것과 없는 것 두 개이다
# 또한 대문자도 다르다

str_to_upper(c("i", "ı"))
## [1] "I" "I"
str_to_upper(c("i", "ı"), locale = "tr")
## [1] "<U+0130>" "I"

로케일은 두 글자 또는 세 글자 줄임말인 ISO 639 언어 코드로 지정된다. 설정하고자 하는 언어의 ISO639 코드를 모르는 경우, 위키피디아에 잘 정리되어 있다. 로케일을 비워 둘 경우에는 운영체제에서 제공한 현재 로케일을 사용한다.

로케일의 영향을 받는 또 다른 중요한 작업은 정렬이다. 베이스R의 order()sort() 함수는 현재 로케일을 사용하여 정렬한다. 다른 컴퓨터에서도 변함없는 동작을 원한다면 로케일 추가인수를 취하는 str_sort()str_order() 를 사용하면 된다.

x <- c("apple", "eggplant", "banana")
str_sort(x, locale = "en")  # English
## [1] "apple"    "banana"   "eggplant"
str_sort(x, locale = "haw") # Hawaiian
## [1] "apple"    "eggplant" "banana"

10.2.5 연습문제

  1. stringr 을 사용하지 않는 코드에서 paste()paste0() 를 종종 볼 것이다. 두 함수의 차이점은 무엇인가? 이들에 상응하는 stringr 함수는 무엇인가? 이 함수들은 NA 를 다룰 때 어떻게 다른가?
  2. str_c()sep 인수와 collapse 인수의 차이를 자신의 말로 기술하라.
  3. str_length()str_sub() 을 이용하여 문자열 중앙 문자를 추출하라. 문자열에 짝수 개의 문자가 있다면 어떻게 하겠는가?
  4. str_wrap() 의 기능은 무엇인가? 어떤 경우에 이 함수를 사용하겠는가?
  5. str_trim() 의 기능은 무엇인가? str_trim() 의 반대는 무엇인가?
  6. 예를 들어 벡터 c( "a", "b", "c") 를 문자열 a, b, c 로 변환하는 함수를 작성하라. 길이가 0, 1, 2인 벡터일 경우 어떻게 해야 하는지에 대해 신중하게 생각해보라.