R 정규표현식 기초 활용과 특수문자 제거

크롤링이나 날 것의 지저분한 문자열 데이터를 다루다 보면 "[셰프찬]"처럼 양옆을 감싸는 불필요한 괄호 안의 문자를 지우거나, 제품명 사이사이에 조잡하게 껴있는 슬래시(/)와 파이프(|) 등 특수문자들을 전부 제거해야 하는 데이터 정비 상황에 늘 봉착합니다.

이럴 때 R의 stringr 패키지와 함께 조합하여 사용하면 상상을 초월하는 위력을 발휘하는 것이 바로 전 세계 프로그래머들의 문자열 통일 규격, 정규표현식(Regular Expression, Regex)입니다. 엄밀히 파고들면 정규표현식은 심해처럼 깊고 방대한 프로그래밍 언어 그 자체이지만, 초보 데이터 분석가가 실무에서 당장 써먹고 가장 빈번하게 마주치는 강력한 필수 기초 활용 콤보 3가지를 깔끔하게 요약해 드립니다.

1. 모든 특수문자, 한 번에 싹 다 찾아내어 폭파하기! [[:punct:]]

실전 상품명이나 댓글 리뷰 데이터에는 우리의 상상을 초월하는 온갖 특이한 특수기호(쉼표, 마침표, 느낌표, 언더바, 대괄호 등)가 무작위로 섞여 있습니다. 이럴 때 코드로 하나하나 기호를 찾아 지울 필요가 절대 없습니다. 마치 무협지의 마법 주문 하나만 코드에 외워주면 됩니다.

library(stringr)
sample_str <- "[닭터의 자연] 닭(볶음용) 1kg!!"

# 이름하여 마법의 구두점(Punctuation) 클래스 색출!
sample_str |> str_replace_all("[[:punct:]]", " ")
> [1] " 닭터의 자연  닭 볶음용  1kg  "

괄호 안에 적힌 [[:punct:]] 라는 구문은 R 정규표현식 엔진상에서 “이 세상 구조상에 존재하는 모든 형태의 구두점 및 특수기호 찌꺼기들 전부”를 뜻하는 예약어입니다. str_replace_all()과 함께 조합하여 안전하게 띄어쓰기 공백(" ")으로 바꿔 달라고 쿨하게 던져놓기만 하면 지저분했던 괄호와 느낌표 연타가 싹 정화됩니다!

2. 특수기호를 일반 문자로 정상 취급하고 싶을 때: 이스케이프 방어막 \

한 가지 골치 아픈 점이자 한계 상황은, 특수기호 중 몇몇 핵심 기호들은 정규표현식 고유의 검색용 명령 문법 구역으로 이미 시스템에 선점, 예약되어 있다는 점입니다. 예를 들어 검색 묶음을 뜻하는 대괄호 [ ], 서브 그룹을 뜻하는 소괄호 ( ), ‘또는(OR)’을 뜻하는 파이프 | 기호, 아무 문자나 매칭하는 뜻의 온점 . 등이 그렇습니다.

따라서 쇼핑몰 크롤링 시 [셰프찬]이라는 문자열 블럭 자체를 검색해서 지우려고 대괄호를 그냥 입력해버리면 컴퓨터는 정규표현식 명령어로 오인하고 에러를 뿜거나 엉뚱한 필터링 짓을 저질러버립니다.

이때 컴퓨터에게 “이거 정규표현식 검색 명령어 아니고, 그냥 문자 형태 디자인인 대괄호 기호 그 자체 그림이야!”라고 외치는 행위를 프로그래밍 용어로 방어막(이스케이프, Escape)이라고 하며 문자 앞단에 역슬래시 두 개 \\ 혹은 \를 달아 방패를 칩니다. (*R에서는 문자열 파싱 구문 특성상 백슬래시 두 개 `\\`를 기본으로 씁니다)

sample_str_2 <- "[셰프찬] 성게 미역국"

# 실패: "[셰프찬]" 이라고 그냥 적으면 대괄호가 정규표현식으로 먹혀 코드가 오작동!
# 성공: 기호 하나하나의 바로 앞에 \\ 를 방패처럼 달아주자!
sample_str_2 |> str_replace("\\[셰프찬\\]", "")
> [1] " 성게 미역국"

참고용 실전 예시: 파이프로 묶인 데이터 벡터 나누기

# "a|b|c|d" 를 에스케이프 처리된 구분자 파이프(\\|)로 쪼개고 싶다면?
"a|b|c|d" |> str_split("\\|")
> [[1]]
> [1] "a" "b" "c" "d"

3. 뚱뚱해진 띄어쓰기 강제 다이어트 시키기: str_trim & str_squish

위 1번 단계에서 요란한 특수기호들을 일괄 공백(" ")으로 막 바꿨더니, 문장 중간과 끝부분에 쓸데없이 스페이스바가 3칸, 4칸씩 연속으로 중복되어 보기 흉해져 버리는 나비효과 부작용이 자주 발생하곤 합니다. 이런 잉여 텍스트 공백 잔여물들을 매우 날씬하게 압축하는 콤보 기술이 탑재되어 있습니다.

messy_string <- "   슬기로운       통계생활      "

# 1단계. 문장 앞/뒤 양끝 끝자락에 붙은 더러운 공백만 잘라내기 (trim)
messy_string <- str_trim(messy_string) 
messy_string
> [1] "슬기로운       통계생활"
# 2단계. 단어 사이사이 중간에 낀 2칸 이상의 다중 무의미 공백들을 1칸으로 꽉 압축하기 (squish)
messy_string |> str_squish()
> [1] "슬기로운 통계생활"

실무 끝판왕 정규 3단 콤보 전처리 (꼭 기억하세요!)

실제 더러운 현업 데이터베이스 전처리 실무 현장에서, 알 수 없는 수천 줄의 상품명을 다듬고 자연어 처리(NLP)를 매길 때 분석가의 손가락이 반사적으로 치고 내려가는 필수 스킬 연계기 콤보입니다!

raw_data <- "[긴급/할인!!]   통영산 생굴(1KG)  ***특가***"

raw_data |> 
    str_replace_all("[[:punct:]]", " ") |> # 1. 특수문자를 죄다 띄어쓰기로 바꾸고
    str_trim() |>                          # 2. 좌우 양극 끝 여백을 싹둑 자른 뒤
    str_squish()                           # 3. 널널하고 남은 띄어쓰기 간격을 1칸으로 쫙 쪼여준다!
> [1] "긴급 할인 통영산 생굴 1KG 특가"

정규표현식은 [a-zA-Z0-9]식으로 너무 복잡하고 깊게 파고들면 초반부터 머리가 아프고 지칠 수 있습니다. 하지만 오늘 배운 글로벌 클래스인 [[:punct:]]와 특수 방어막인 이스케이프 \\ 기법, 그리고 마무리 청소기 squish() 콤보만 시스템처럼 자유자재로 사용할 줄 안다면, 세상 어떤 더러운 텍스트가 당신의 앞을 막아도 완벽히 깔끔한 데이터로 부활시킬 수 있습니다!


당신이 좋아할 만한 콘텐츠

by Google Adsense


관련 글 보기