본문 바로가기

R 데이터분석 문자열 전처리 paste, strsplit, str_detect

R Programming/Basic by Mandarim_ 2023. 10. 1.

R은 문자열 전처리를 위한 함수들이 존재한다.

알아두면 정말 편한 함수에 대해서 정리해보자.


(1) paste(), paste0(): 문자열을 결합해주는 함수.

  • paste() 함수는 collapse 문자를 기준으로 vector 속 문자열을 하나로 결합해준다.
  • paste0() 함수는 빈칸 없이 vector 속 문자열을 결합해준다.
paste(c("사과", "바나나", "딸기", "포도"), collapse = "와 ")
# (결과) "사과와 바나나와 딸기와 포도"

paste(c("사과", "바나나", "딸기", "포도"), collapse = ", ")
# (결과) "사과, 바나나, 딸기, 포도"

paste(c("사과", "바나나", "딸기", "포도"), collapse = "")
paste0("사과", "바나나", "딸기", "포도")
# (둘은 같은 결과) "사과바나나딸기포도"

 

만약 전체를 하나의 문자열로 결합하는 것이 아닌, 아래의 예시처럼 여러 문자열에 대한 결합 결과가 필요할 수도 있다.

다음과 같이 sep을 사용하면 된다.

area <- c("관악구", "용산구", "마포구", "영등포구", "강남구", "동작구")
paste("서울", area, sep = "시 ")

# (결과) 
# [1] "서울시 관악구"   "서울시 용산구"   "서울시 마포구"   "서울시 영등포구"
# [5] "서울시 강남구"   "서울시 동작구"

 

데이터 프레임에서도 물론 작동한다.

area$시군구 <- paste(area$시, area$구, sep = "시 ")
area[,c("시", "구", "시군구")]

# (결과)
#     시       구          시군구
# 1 서울   관악구    서울시 관악구
# 2 서울   용산구    서울시 용산구
# 3 서울   마포구    서울시 마포구
# 4 서울   영등포구  서울시 영등포구
# 5 서울   강남구    서울시 강남구
# 6 서울   동작구    서울시 동작구

 

(주의) collapse option 은 항상 하나의 문자열을 만들어준다!

아래는 잘못 의도된 코드의 예시이다.

> area$시군구 <- paste(area$시, area$구, collapse = "시 ")
> area[,c("시", "구", "시군구")]

# (결과)
#	시       구
#1 서울   관악구
#2 서울   용산구
#3 서울   마포구
#4 서울 영등포구
#5 서울   강남구
#6 서울   동작구
#                                                                          시군구
#1 서울 관악구시 서울 용산구시 서울 마포구시 서울 영등포구시 서울 강남구시 서울 동작구
#2 서울 관악구시 서울 용산구시 서울 마포구시 서울 영등포구시 서울 강남구시 서울 동작구
#3 서울 관악구시 서울 용산구시 서울 마포구시 서울 영등포구시 서울 강남구시 서울 동작구
#4 서울 관악구시 서울 용산구시 서울 마포구시 서울 영등포구시 서울 강남구시 서울 동작구
#5 서울 관악구시 서울 용산구시 서울 마포구시 서울 영등포구시 서울 강남구시 서울 동작구
#6 서울 관악구시 서울 용산구시 서울 마포구시 서울 영등포구시 서울 강남구시 서울 동작구

[응용] paste with for() loop

특히 특정 파라미터에 따라 for문으로 반복되는 결과를 저장할 때 사용하면 편하다.

e.Grid <- expand.grid(nn = c(10000),
            tr_beta = c(0, 0.5, 1),
            prob = c(0.5, 0.3, 0.1, 0.05))


results <- NULL
en <- nrow(e.Grid)

for(i in 1:en) {
  print(i)
  tt1 <- Sys.time()
  nn <- e.Grid$nn[i]; tr_beta <- e.Grid$tr_beta[i]; 
  p <- c(e.Grid$prob[i], 1-e.Grid$prob[i]) 
  
  # << 어떠한 results 만드는 중 >>
  
  write.csv(results, paste0("./Results_n", nn, "_p", p[1], "_b", tr_beta, ".csv"))
}

혹은 assign과 함께 사용하기 편하다.

아래는 ggplot 을 저장하는 예시이다.

 

2022.08.07 - [R 프로그래밍/시각화] - [R] for 문으로 그래프 생성: ggplot2, for, assign, paste

 

[R] for 문으로 그래프 생성: ggplot2, for, assign, paste

ggplot과 for문 앞 장에서 여러 그래프 한 번에 타나내는 법을 다루었다. 그래프를 하나씩 g1, g2로 정의하여 gird.arrange() 함수를 이용하여 나타내면 된다. 하지만, 나타내려는 그래프 수가 10개를 넘

hyemstat.tistory.com


(2) strsplit(): 문자열을 특정 기준으로 분리하는 함수

  • strsplit() 함수는 string을 특정 구분 기호에 따라 분리해주는 함수이다,
  • 단, 반환될 때 list 형식으로 반환해주므로 이를 주의해서 사용해야 한다.
area <- c("관악구", "용산구", "마포구", "영등포구", "강남구", "동작구")
text <- paste("서울", area, sep= "시 ")

split_area <- strsplit(text, "시 ")
split_area

# [[1]]
# [1] "서울"   "관악구"
# 
# [[2]]
# [1] "서울"   "용산구"
# 
# [[3]]
# [1] "서울"   "마포구"
# 
# [[4]]
# [1] "서울"     "영등포구"
# 
# [[5]]
# [1] "서울"   "강남구"
# 
# [[6]]
# [1] "서울"   "동작구"

 apply 계열의 함수들을 이용하여 원하는 부분을 쉽게 가지고 올 수 있다!

unlist(lapply(text, function(t) strsplit(t, "시 ")[[1]][1]))
# [1] "서울" "서울" "서울" "서울" "서울" "서울"

unlist(lapply(text, function(t) strsplit(t, "시 ")[[1]][2]))
# [1] "관악구"   "용산구"   "마포구"   "영등포구" "강남구"   "동작구"

(3) str_detect(): 해당 문자열이 특정 패턴을 포함하는지 확인하는 함수

  • stringr 패키지의 str_detect() 함수는 string에 특정 pattern이 있는지를 확인하고, TRUE/FALSE를 반환해주는 함수이다.

아래와 같은 문자열 자료가 존재할 때, 

이 자료를 normal 이면 normal 그룹으로 tumor 면 tumor 그룹으로 정리하고 싶을 때 사용한다.

print(p_GSE26910$title)

# [1] "prostate normal 1" "prostate tumor 1"  "prostate normal 2" "prostate tumor 2" 
# [5] "prostate normal 3" "prostate tumor 3"  "prostate normal 4" "prostate tumor 4" 
# [9] "prostate normal 5" "prostate tumor 5"  "prostate normal 6" "prostate tumor 6" 
# [13] "breast normal 1"   "breast tumor 1"    "breast normal 2"   "breast tumor 2"   
# [17] "breast normal 3"   "breast tumor 3"    "breast normal 4"   "breast tumor 4"   
# [21] "breast normal 5"   "breast tumor 5"    "breast normal 6"   "breast tumor 6"

str_detect(string=p_GSE26910$title, pattern="tumor")
# [1] FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE
# [14]  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE

factor(ifelse(str_detect(string=p_GSE26910$title, pattern="tumor"), "Tumor", "Normal"))
# [1] Normal Tumor  Normal Tumor  Normal Tumor  Normal Tumor  Normal Tumor  Normal
# [12] Tumor  Normal Tumor  Normal Tumor  Normal Tumor  Normal Tumor  Normal Tumor 
# [23] Normal Tumor 
# Levels: Normal Tumor

[응용] 해당 문자열이 여러 패턴을 포함하는지 확인

만약 여러 패턴을 탐색해야 할 때, 복잡하게 if문을 여러 번 쓰지 않아도 다음과 같이 사용가능하다.

다음의 자료를 활용하여 "T"와 "Tumor" 포함하면 Tumor 그룹으로, 아니면 Normal 그룹으로 분류해보겠다.

 

이 때 "또는"의 의미를 갖는 "|"를 활용할 수 있다.

포함시켜야 하는 패턴이 많다면, [1]에서 소개된 paste를 사용하면 편하다.

c(p_GSE3744$title, p_GSE26910$title)
# [1] "T118 U133p2"       "T134 U133p2"       "T140 U133p2"       "T141 U133p2"      
# [5] "T146 U133p2"       "T147 U133p2"       "T149 U133p2"       "T133 U133p2"      
# [9] "T21 U133p2"        "T56 U133p2"        "T116 U133p2"       "T144 U133p2"      
# [13] "T129 U133p2"       "T143 U133p2"       "T38 U133p2"        "T123 U133p2"      
# [17] "T137 U133p2"       "T130 U133p2"       "T151 U133p2"       "T152 U133p2"      
# [21] "T37 U133p2"        "T183 U133p2"       "T117 U133p2"       "T161 U133p2"      
# [25] "T30 U133p2"        "T84 U133p2"        "T115 U133p2"       "T44 U133p2"       
# [29] "T81 U133p2"        "T50 U133p2"        "T4 U133p2"         "T175 U133p2"      
# [33] "T178 U133p2"       "T41 U133p2"        "T73 U133p2"        "T92 U133p2"       
# [37] "T74 U133p2"        "T162 U133p2"       "T145 U133p2"       "T119 U133p2"      
# [41] "NB42 U133p2"       "NB58 U133p2"       "NB60 U133p2"       "NB64 U133p2"      
# [45] "NB69 U133p2"       "NB83 U133p2"       "NB87 U133p2"       "prostate normal 1"
# [49] "prostate tumor 1"  "prostate normal 2" "prostate tumor 2"  "prostate normal 3"
# [53] "prostate tumor 3"  "prostate normal 4" "prostate tumor 4"  "prostate normal 5"
# [57] "prostate tumor 5"  "prostate normal 6" "prostate tumor 6"  "breast normal 1"  
# [61] "breast tumor 1"    "breast normal 2"   "breast tumor 2"    "breast normal 3"  
# [65] "breast tumor 3"    "breast normal 4"   "breast tumor 4"    "breast normal 5"  
# [69] "breast tumor 5"    "breast normal 6"   "breast tumor 6"

t_pattern <- paste(c("T", "tumor"), collapse="|") # "T|tumor"
str_detect(string = c(p_GSE3744$title, p_GSE26910$title), 
+          pattern = t_pattern)
# [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
# [14]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
# [27]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
# [40]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE
# [53]  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE
# [66] FALSE  TRUE FALSE  TRUE FALSE  TRUE

 

반응형