Py) TM - 정규표현식-05(공백)

Py) TM - 정규표현식-05(공백)

Pandas 객체 기반 정규표현식을 활용해서 공백을 처리하는 여러 방법에 대해 알아본다.


개요

텍스트를 다룸에 있어 공백은 반드시 처리해야 하는 부분이다. 특히 사람이 작성하는 텍스트는 올바른 위치에 띄어쓰기를 한다는 보장이 없기 때문에 데이터 전처리 또는 텍스트 마이닝을 위한 공백 처리가 필요하다. 띄어쓰기를 잘못해서 띄어쓰기가 필요한 곳에 띄어쓰가 제대로 되어있지 않은 경우 PyKoSpacing(R은 KoSpacing)을 사용할 수 있다. 하지만 여기서는 정규표현식을 사용하여 불필요한 띄어쓰기를 제거하는 방법에 대해 알아본다.

이론

앞 뒤 공백 매칭

사용자의 오타 또는 문단의 시작 등의 이유로 앞 또는 뒤 부분에 공백이 있을 수 있다. 이 때 다음의 정규식을 사용할 수 있다.

"^ ": 한 칸 띄어쓰기로 시작하는
" $": 한 칸 띄어쓰기로 끝나는
"^ | \$": 한 칸 띄어쓰기로 시작하거나 끝나는

참고로 앞 뒤의 공백을 제거하기 위해서는 정규표현식을 쓰지 않고도 .str.strip() 메서드로 처리할 수 있다.

2개 이상의 공백 매칭

텍스트 처리 시 예외사항이 많이 발생하기 때문에 되도록이면 한 번에 여러 예외사항을 처리할 수 있는 코드를 작성하는 것이 좋다. 그래서 띄어쓰기 두 칸, 세 칸 등등 대중 띄어쓰기를 매칭하기 위해 일일이 정규식을 명시하는 대신에 한 번에 매칭하기 위해서는 다음과 같은 정규식을 사용할 수 있다.

" {2,}": 두 칸 이상의 띄어쓰기
"^ {1,}": 한 칸 이상의 띄어쓰기로 시작하는
" {1,}$": 한 칸 이상의 띄어쓰기로 끝나는

“^ {1,}| {1,}$”: 한 칸 이상의 띄어쓰기로 시작하거나 한 칸 이상의 띄어쓰기로 끝나는

“^ {1,}| {1,}$” 정규식의 경우 앞에서 소개한 .str.strip() 메서드를 사용하는 것과 완전히 같다. Pandas 객체 기반으로 정규식을 사용할 경우 해당 메서드를 사용하면 되지만, 혹시나 re 라이브러리를 활용하여 텍스트를 처리해야 할 경우 해당 정규식을 사용하거나 .strip() 메서드를 사용해야 할 수 있으니 참고하도록 하자.

탭 매칭

띄어쓰기로 보이지만 아닌 것이 존재하는데 그 중 대표적인 것이 탭(tab)이다. 탭과 관련한 정규식은 다음과 같다.

"\t": 단일 탭
"\t{1,}": 한 개 이상의 탭
"^\t{1,}|\t{1,}$": 한 개 이상의 탭으로 시작하거나 끝나는

참고로 “^\t{1,}|\t{1,}$” 정규식도 역시 앞에서 소개한 .str.strip() 메서드를 사용하는 것과 완전히 같다.

특수 공백 제거

매우 드물지만 텍스트에 유니코드(Unicode)로 표현되는 특수한 공백이 존재하기도 한다. 관련 공백 목록은 다음과 같다.

  • Non-breaking Space(U+00A0): 단어 사이의 줄 바꿈을 방지하는 공백
  • Em Space(U+2003): 대략 ‘M’의 너비에 해당하는 공백
  • En Space(U+2002): 대략 ‘N’의 너비에 해당하는 공백
  • Thin Space(U+2009): 매우 얇은 공백

해당 유니코드 공백을 처리하기 위해서는 정규식을 “\u00A0” 과 같이 사용해야 하며 어떠한 방법으로도 공백이 제거되지 않을 때 혹시 이 유니코드로 작성이 된 공백이 아닌지 의심하길바란다.

실습

이론 부분에서 언급한 내용을 실습하기 위해 다음과 같이 라이브러리와 데이터를 준비한다.

1
2
3
4
import pandas as pd

ser = pd.Series([" abc", "ab c ", " ab c", " abc ", "abc ",
" a bc ", " abc "])

다음의 코드와 앞의 이론을 매칭해서 어떤 정규식이 어떻게 처리되는지 확인하면 되겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
ser.str.strip()
## 0 abc
## 1 ab c
## 2 ab c
## 3 abc
## 4 abc
## 5 a\tbc
## 6 abc
## dtype: object

ser.str.strip().str.len()
## 0 3
## 1 4
## 2 5
## 3 3
## 4 3
## 5 4
## 6 3
## dtype: int64

ser.str.replace("\t", "✅", regex = True)
## 0 abc
## 1 ab c
## 2 ab c
## 3 abc
## 4 abc
## 5 ✅a✅bc✅
## 6 ✅abc✅✅
## dtype: object

ser.str.replace("\t{1,}", "✅", regex = True)
## 0 abc
## 1 ab c
## 2 ab c
## 3 abc
## 4 abc
## 5 ✅a✅bc✅
## 6 ✅abc✅
## dtype: object
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×