728x90
반응형

 지금까지 문자열(string) type을 생성하고 이스케이프 문자, 포맷팅에 대해 학습해보았다. 지금까지 학습한 내용은 문자열을 생성하는 것에 관련 있는 것이지, 문자열을 다루는 내용과는 거리가 멀다고 할 수 있다.

 이번 포스트에서는 문자열을 직접 가지고 노는 문자열 전처리 코드에 대해 학습을 해보겠다.

 

 

문자열 전처리

1. 문자열 연산

 문자열 연산은 우리가 일반적으로 아는 더하기, 빼기, 곱하기와 같은 기능으로, 앞서 학습했던 List에서의 더하기, 곱하기처럼 문자A + 문자B는 문자A문자B가 되며, 문자 A * 3은 문자A문자A문자A가 된다.

# 1. 문자열을 더해보자
>>> A = "Python"
>>> B = "is"
>>> C = "easy"
>>> D = "and"
>>> E = "useful"
>>> F = A + " " + B + " " + C + " " + D + " " + E
>>> print(F)
Python is easy and useful


# 2. 문자열을 곱해보자
>>> A * 2
'PythonPython'


# 3. 문자열을 더하고 곱해보자
>>> G = A + " "
>>> print(G * 3)
Python Python Python 
  • 문자열 더하기는 꽤 유용하게 사용할 수 있는 기능으로, 포맷팅과 동일하게 사용할 수도 있다.
# 문자열 더하기를 포맷팅처럼 사용해보자
>>> AB = A + " " + B + " "
>>> print(AB + C)
>>> print(AB + E)
Python is easy
Python is useful

 

위와 같은 산술 연산 기호를 사용하는 것은 아니지만 문자열 빼기도 가능하다

# 생성된 문자열 F에서 and를 제거해보자
>>> print(F)
Python is easy and useful

>>> F.replace("and ", "")
'Python is easy useful'


# 문자열 F에서 and를 or로 바꿔보자
>>> F.replace("and", "or")
'Python is easy or useful'
  • 문자열 빼기가 문자열 F에서 문자열 D를 제거하는 것이라면, replace 함수를 응용해서 사용할 수 있다.
  • replace(): 문자열.replace(대상 문자, 바꿀 문자) 함수를 사용하면, 대상 문자를 내가 원하는 다른 문자로 바꿀 수 있다.

 

 

 

2. 문자열 인덱싱(슬라이싱)

 문자열 인덱싱은 문자에서 내가 원하는 구간의 문자만 선택하는 방법이다.

# 위에서 생성했던 문자열 F를 가지고 indexing을 해보자
>>> print(F)
'Python is easy and useful'


# 1. 먼저 문자 전체의 길이를 확인해보자
>>> len(F)
25


# 2. 문자열 F에서 첫 문자부터 5번째 문자까지 가지고 와보자
>>> F[0:5]
'Pytho'

# 2.1. 문자열 F를 뒤에서 6번째부터 뒤 모든 문자를 가지고 와보자
>>> F[-6:len(F)]
'useful'

>>> F[-6:]
'useful'
  • len(x): len 함수는 들어간 문자의 길이를 반환한다. x에 list나 DataFrame 등이 들어가는 경우, list는 원소의 수, DataFrame은 Row의 수를 반환한다.
  • 인덱싱에서 [n1:n2] n1에 아무것도 넣지 않는 경우 처음부터인 0을 의미한다. n2에 아무것도 넣지 않는 경우 마지막 위치를 의미한다.
  • 인덱싱한 값을 다른 변수에 담으면, 슬라이싱(부분만 가져오기)이 된다.
# 슬라이싱 기능을 활용하면 원하는 위치만 제거 혹은 다른 문자 끼워넣기가 가능하다.
>>> print(F)
'Python is easy and useful'

# 1. "easy and "를 제거해보자
>>> F[:10] + F[-6:]
'Python is useful'

# 2. useful을 useless로 바꿔보자
>>> F[:10] + F[-6:-3] + "less"
'Python is useless'

 

 위 인덱싱에선 내가 찾고자 하는 문자의 위치를 직접 확인해야 했으나, 문자 위치를 반환하는 함수인 find(), index() 함수를 사용하면, 위치를 수월하게 찾을 수 있다.

# 문자열 F에서 and의 위치를 찾아보자
>>> print(F)
'Python is easy and useful'

>>> F.find("and")   
15
>>> F[15:]
'and useful'    # 단어의 시작 위치가 출력된다.

# index() 함수는 find() 함수와 동일한 기능을 한다.
>>> target_start = F.index("and")
>>> print(target_start)
15

# len() 함수를 섞어서 사용하면 이 문제를 해결할 수 있다.
>>> F[target_start:target_start+len("and")]     # 문자 끝 위치 = 문자 시작 위치 + 문자 길이
'and'
  • 문자열.find(탐색 문자), 문자열.index(탐색 문자) 함수를 사용하면, 해당 문자가 처음 등장한 문자의 위치를 알 수 있다.
  • len() 함수와 섞어서 사용한다면 문자의 끝 위치도 알 수 있다.
  • 그러나 만약, 해당하는 문자가 여러개라면 가장 왼쪽에서 등장한 문자의 위치만 반환한다는 단점이 있다(이는 추후 학습할 정규표현식 함수를 사용하면 수월하게 해결할 수 있다).
  • index() 함수와 find() 함수의 차이는 대상 단어가 없을 때로, find() 함수 사용 시 대상 단어가 없으면 -1이 반환되고, index() 함수는 에러가 발생한다.

 

 

 

3. list와 str

 str type과 list type을 오가게 하는 함수가 있으며, 이를 단순히 말하면 아래와 같다.

  • "구분자".join(대상 문자열): 합치기
  • "대상 문자열".split("구분자"): 쪼개기
>>> target = "Python is fun and useful"

# 1. 문자열을 list로 쪼개보자
>>> target_list = target.split(" ")
>>> print(target_list)
['Python', 'is', 'fun', 'and', 'useful']

# 2. list를 문자열로 합쳐보자
# _(Under bar)로 합쳐보자
>>> target_str = "_".join(target_list)
>>> print(target_str)
Python_is_fun_and_useful

# 3. 생성된 단어를 한 글자 단위로 잘라보자
# join() 함수를 문자열을 대상으로 사용하면, 문자열에서 단어 하나하나 사이에 특정 단어가 들어간다.
>>> put_separator = "|".join(target_str)
>>> print(put_separator.split("|"))
['P', 'y', 't', 'h', 'o', 'n', '_', 'i', 's', '_', 'f', 'u', 'n', '_', 'a', 'n', 'd', '_', 'u', 's', 'e', 'f', 'u', 'l']
  • join() 함수를 문자열을 대상으로 사용 시, 문자열의 단어 하나하나 사이에 join 단어가 들어간다.
  • |는 거의 사용하지 않는 특수 문자 중 하나로 일반적으로 Rawdata에 존재하지 않는다.
  • join() 함수와 split() 함수를 섞어서 사용하면 한 단어 단위로 자를 수 있다.

 

 

 

4. 공백 제거하기

# Target
>>> target = " Python is easy and useful "

# 1. 앞의 공백을 제거하자
>>> target.lstrip()
'Python is easy and useful '

# 2. 뒤의 공백을 제거하자
>>> target.rstrip()
' Python is easy and useful'

# 3. 양쪽 공백을 제거하자
>>> target.strip()
'Python is easy and useful'

# 4. 모든 공백을 제거하자
>>> target.replace(" ", "")
'Pythoniseasyanduseful'
  • 문자열.lstrip(): 왼쪽 공백 제거
  • 문자열.rstrip(): 오른쪽 공백 제거
  • 문자열.strip(): 양쪽 공백 제거
  • 문자열.replace(" ", ""): 모든 공백 제거

 

 

 

5. 대소문자 바꾸기

# Target
>>> target = "Python is easy and useful"

# 1. 소문자를 대문자로 바꿔보자
>>> upper_T = target.upper()
>>> print(upper_T)
PYTHON IS EASY AND USEFUL

# 2. 대문자를 소문자로 바꿔보자
>>> upper_T.lower()
'Python is easy and useful'
  • 문자열.upper(): 소문자를 대문자로 만든다
  • 문자열.lower(): 대문자를 소문자로 만든다

 

 

 

6. 문자열 개수 세기

# target
>>> target = "Python is fun and useful"

# 1. 문자열 전체 길이를 확인해보자
>>> len(target)
25

# 2. 문자열 안에 특정 문자가 몇 개 있는지 확인해보자
>>> target.count(" ")
4

>>> target.count("Python")
1

 

 

 

 지금까지 문자열을 다루는 기본적인 함수에 대해 알아보았다. 위 함수들을 보면, 내가 원하는 단어를 탐색하고 조작하는 부분이 실전에서 필요한 것에 비해 부족하다는 것이 느껴지는데, 이를 보다 체계적으로 할 수 있는 방법이 바로 정규표현식이다.

 다음 포스트에서는 파이썬 정규표현식에 대해 학습해보도록 하겠다.

728x90
반응형
728x90
반응형

  예를 들어 당신이 어떠한 반복되는 문자열을 만드려고, 하고 그 중 일부분만 바꿔야 한다면 어떻게 하겠는가?

# 예를 들어 뽀로로, 크롱의 인사와 짱구, 짱아의 인사 문자열을 생성하려면 어떻게 해야할까?
>>> str0 = "뽀로로: \"크롱 반가워!\"\n크롱:\"오! 뽀로로 좋은 아침이야!\""
>>> str1 = "짱구: \"짱아 반가워!\"\n짱아:\"오! 짱구 좋은 아침이야!\""
>>> print(str0)
>>> print("\n")
>>> print(str1)
뽀로로: "크롱 반가워!"
크롱:"오! 뽀로로 좋은 아침이야!"

짱구: "짱아 반가워!"
짱아:"오! 짱구 좋은 아침이야!"

 위 예시처럼 일일이 그 문자열을 만들어 새로 지정해 줄 것인가? 이는 매우 비 경제적인 방법인데, 이번 포스트에선 문자열의 일부를 손쉽게 바꿀 수 있는 방법인 문자열 포맷팅에 대해 학습해보겠다.

 

 

문자열 포맷팅(String Formatting)

 지난 포스트인 이스케이프 문자 예제에서 뽀로로, 크롱과 같은 문자열 내 특정 문자가 반복되어 출력되는데, 이 부분만 자동으로 바꿀 수 있다면, 보다 적은 코드만 써도 되지 않을까? 라는 생각이 들지 않는가?

 문자열 포맷팅은 코드를 더 경제적으로 쓸 수 있는 방법 중 하나로, 출력되는 문자열에서 일부분만 쉽게 바꿀 수 있는 방법 중 하나다.

 문자열 포맷팅은 크게 3가지 방법이 있다.

  1. % formating
  2. {} formating
  3. f-string

 

 

1. % formating

# 1. % formating
>>> print("%s: %s, 반가워!" %("뽀로로", "크롱"))
>>> print("%s: %s, 좋은 아침이야!" %("크롱", "뽀로로"))
뽀로로: 크롱, 반가워!
크롱: 뽀로로, 좋은 아침이야!
  • 위 예시를 보면, %s라는 문자와 %()라는 처음 보는 문자가 들어간 것을 볼 수 있다.
  • %s %d % ("str", 2) 이 기본적인 방식이다. 여기서 %s, %d와 같은 문자를 문자열 포맷 코드라고 한다.
  • 문자열 포맷 코드는 다음과 같다.
코드 설명 코드 설명
%s 문자열(string) %d 정수(integer)
%c 문자 1개(character) %f 부동소수(floating-point)
  • 참고로 %s의 경우 문자형이나, 숫자, 소수 모두 문자형으로 변형이 가능하므로, %s를 넣는 경우, 모든 형태의 값을 넣을 수 있다.
  • 이 밖에도 8진수(%o), 16진수(%x)가 더 있긴 하지만, %s, %d, %f만 사용할 수 있어도 충분하다.
  • 참고로 %를 문자로 그냥 출력하고 싶다면 %%를 입력해야한다.
# 위 코드를 좀 더 쉽게 써보자
>>> name1 = "뽀로로"
>>> name2 = "크롱"
>>> print("%s: %s, 반가워! \n%s: %s, 좋은 아침이야!" %(name1, name2, name2, name1))
뽀로로: 크롱, 반가워! 
크롱: 뽀로로, 좋은 아침이야!

>>> name3 = "짱구"
>>> name4 = "짱아"
>>> print("%s: %s, 반가워! \n%s: %s, 좋은 아침이야!" %(name3, name4, name4, name3))
짱구: 짱아, 반가워! 
짱아: 짱구, 좋은 아침이야!
  • 위 코드 같이 반복 출력하고자 하는 Data("뽀로로", "크롱")를 변수(name1, name2)에 담아서 사용하면 보다 쉽게 쓸 수 있다.
  • 그러나 위 방법의 경우, 문자를 넣어주고 싶은 위치랑 %()안의 변수 위치가 동일해야하므로, Data가 문자열에서 들어갈 위치를 헷깔릴 수 있다는 단점이 있다.

 

 

 

2. {} formating

# {} formating을 써보자
print("{name1}: {name2}, 반가워!\n{name2}: 오! {name1} 좋은 아침이야!".format(name1="뽀로로", name2="크롱"))
뽀로로: 크롱, 반가워!
크롱: 오! 뽀로로 좋은 아침이야!
  • {} format은 문자열 내에 원하는 변수를 지정하여 사용할 수 있다.
  • % formating과 달리 변수의 위치를 구체적으로 알 수 있다.
  • 이를 def 코드를 사용해서 함수로 만든다면, 보다 효율적으로 사용할 수 있다.
# def 코드를 사용해서 만들어보자
>>> def hello(name1, name2):
>>>     print("{name1}: {name2}, 반가워!\n{name2}: 오! {name1} 좋은 아침이야!".format(name1=name1, name2=name2))
    
>>> hello("짱구", "짱아")

짱구: 짱아, 반가워!
짱아: 오! 짱구 좋은 아침이야!
  • 그러나, 이 방법은 .format(변수이름=변수)를 넣어줘야하기 때문에 코드가 길어진다는 단점이 있다.

 

 

 

3. f-string

% formating과 {} formating을 비교해보면, 각각 코드를 만드는 데에 있어 장점과 단점이 나뉘는 것을 알 수 있다.

  • % formating은 문자열 포맷팅 밖에서 지정한 변수를 가져갈 수 있다.
  • {}.formating은 문자열 내 포맷팅 된 변수들의 위치를 알 수 있다.
  • 위 장점을 적절히 섞는다면 보다 코드를 수월하게 짤 수 있지 않을까? > f-string을 통해 이를 해결할 수 있다.
# f-string 포맷팅을 사용해보자
>>> name1 = "뽀로로"
>>> name2 = "크롱"
>>> print(f"{name1}: {name2}, 반가워!\n{name2}: 오! {name1} 좋은 아침이야!")
뽀로로: 크롱, 반가워!
크롱: 오! 뽀로로 좋은 아침이야!
  • f-string은 위 % formating이나 {} formating보다 코드가 단순하다.
  • 문자열 밖에서 문자열에 들어갈 가변적인 변수를 지정하고, 문자열 앞에 f를 붙이면 된다.
  • 문자열 내에선 {} formating과 같은 방식으로 문자열을 적으면 된다.
  • 위 코드를 def 코드를 이용해서 함수로 만들어보자.
# 함수화 해보자
>>> def hello(name1, name2):
>>>     print(f"{name1}: {name2}, 반가워!\n{name2}: 오! {name1} 좋은 아침이야!")
    
>>> hello("짱구", "짱아")


짱구: 짱아, 반가워!
짱아: 오! 짱구 좋은 아침이야!
  • 위의 {} formating을 사용해서 만든 함수보다 코드가 단순하다는 것을 알 수 있다.

 

 

 

 지금까지 문자열의 일부만 바꾸는 방법인 문자열 포맷팅에 대해 알아보았다. 이 중 f-string이 가장 코드가 단순하고, 직관적이므로, 가능하면 f-string을 쓰길 바란다.

 다음 포스트에서는 문자열을 가지고 노는 방법인 문자열 전처리에 대해 학습해보겠다.

728x90
반응형
728x90
반응형

 지난 포스트에서는 Python의 기본적인 자료형에 대해 공부해보았다. "Python-기초: 1.0. 자료형(1) - scalar"에서 Data type으로 int, float, None, Boolean은 나왔으나, 정작 문자열은 나오지 않았다.

 이번 포스트에서는 data type 중 문자열 Type인 string에 대해 심도 깊게 다뤄보도록 하겠다. 

 

 

문자열(String)

  • Python에서 문자열은 ''(Quotation)나 ""(Double Quotation) 안에 문자를 넣어서 만든다.
  • Python의 기본 인코딩은 utf-8이므로, R과 달리 한글에 대한 텍스트 마이닝이 깔끔하게 잘 수행된다.
  • 문자열 데이터를 처리하여, 그 안에 숨어 있는 정보를 찾아내는 전반적인 과정을 텍스트 마이닝(Text Mining)이라 한다.

※ 텍스트마이닝(Text Mining)

  • 현장에서 접하는 대다수의 데이터는 숫자로 이루어진 연속형 데이터보다 Log Data 같은 문자, 사진 같은 이미지, 동영상, 음악과 같은 비정형 데이터가 대부분이다.
  • 대부분의 전처리(Data Handling)는 이러한 비정형 데이터를 분석에 용이한 숫자 데이터로 변환해주는 과정이다.
  • 문자형 Data를 연속형 데이터로 변환하는 경우, 크게 2가지 방법이 있다.
    1. 범주화: 문자에 해당하는 숫자를 배정 - 리소스를 덜 먹음
    2. 벡터화: One-Hot Vector, Word2Vec 등의 방법 사용 - 일반적으로 기계학습에서 사용

 

 

 

문자열 Data를 만들어보자

# 문자열 Data를 만들어보자.
# 1. "" or ''를 사용해서 만든다.
>>> str1 = "Python is very useful"
>>> print(str1)
Python is very useful

>>> str2 = 'Python is a lot of fun'
>>> print(str2)
Python is a lot of fun

>>> str3 = """Python is easy and fun"""
>>> print(str3)
Python is easy and fun

>>> str4 = '''So let's do Python'''
>>> print(str4)
So let's do Python
  • 문자열 Data는 ""나 ''를 사용해서 만들며, "나 ' 기호를 3번 연속 사용해서 만들 수도 있다.
  • 보통 """나 '''로 만드는 경우는 긴 문장이나 주석을 넣을 때 사용한다.
# 문자열 안에 문자열 생성 기호인 ''나 ""를 넣고 싶은 경우엔 어떻게 할까?
>>> print("Let's do our best today")
Let's do our best today

>>> print('Pororo said "Hello" to Crong')
Pororo said "Hello" to Crong

>>> Frozen = """
    Anna:
    "Elsa?  Do you want to build a snowman?
    "Come on let's go and play.
    I never see you anymore. Come out the door.
    It's like you've gone away.
    We used to be best buddies
    And now we're not. I wish you would tell me why.
    Do you want to build a snowman?
    It doesn't have to be a snowman."

    Elsa:
    "Go away, Anna."

    Anna:
    "...Okay bye."
    """
    
>>> print(Frozen)

Anna:
"Elsa?  Do you want to build a snowman?
"Come on let's go and play.
I never see you anymore. Come out the door.
It's like you've gone away.
We used to be best buddies
And now we're not. I wish you would tell me why.
Do you want to build a snowman?
It doesn't have to be a snowman."

Elsa:
"Go away, Anna."

Anna:
"...Okay bye."
  • 짧은 문장 안에 '나 "가 들어가야한다면 그에 상응하는 문자로 묶어주면 된다.
  • 그러나 이 두 가지가 모두 들어가야한다면, """ 문장 """으로 묶어주면 된다.
  • 또는 escape 문자인 \을 사용하면 된다.

 

 

 

이스케이프 문자(Escape Sequence)

파이썬을 포함한 각종 언어에서는 잘 사용하지 않는 특수 문자나 특수문자 + 문자 조합에 특정 기능을 넣어 놓는다. 그러나, 가끔 이 이스케이프 문자가 실제 문자 Data 대상인 경우도 있기 때문에 이스케이프 문자가 아님을 알려주는 방법을 숙지할 필요가 있다.

이스케이프 문자 이름 설명
\b 벡스페이스 뒤로 한 칸 삭제
\t 문자열 사이에 탭 간격 생성
\n 라인피드 줄 바꿈
\f 폼피드 현재 커서를 다음 줄로 이동
\r 캐리지 현재 커서를 가장 앞으로 이동
\\ 역슬래시 \를 이스케이프 문자 앞에 사용하는 경우 그대로 출력
  • 위 표에서 많이 사용되는 것은 탭, 라인피드, 이스케이프 문자 앞에 \ 사용하기이므로, 나머지 이스케이프 문자에 대해선 크게 신경 쓰지 말자.
  • 키보드에서 \는 존재하지 않는데, ₩ 키가 동일한 기능을 한다.
# 이스케이프 문자를 사용해보자
>>> str5 = "뽀로로: \"크롱 반가워!\"\n크롱:\"오! 뽀로로 좋은 아침이야!\""
>>> print(str5)
뽀로로: "크롱 반가워!"
크롱:"오! 뽀로로 좋은 아침이야!"

# 이스케이프 문자를 그대로 출력시켜보자
>>> str5 = "뽀로로: \"크롱 반가워!\"\\n크롱:\"오! 뽀로로 좋은 아침이야!\""
뽀로로: "크롱 반가워!"\n크롱:"오! 뽀로로 좋은 아침이야!"

 

  • 위 예제에서 역 슬래시 사용 후 "나 ' 같은 특정 기능이 들어간 특수 문자를 넣으면 그대로 출력되는 것을 알 수 있다.
  • 이스케이프 문자에서 \n나 \t는 Data를 line 단위로 가져오기, tap 단위로 구분 지어 가져오기(구분자)를 하는 경우에 문자 안에 해당 문자가 들어 있어, Row를 잘못 인식할 수도 있다(실제 Row의 수보다 더 많은 Row를 생성).
  • 텍스트 데이터를 다룰 때, 이스케이프 문자나 ' or "로 인해 의도치 않은 결과가 출력 될 수 있다.

 

 

 

 이번 포스트에서는 가볍게 문자열을 만드는 방법과 이스케이프 문자에 대해 알아보았다. 이스케이프 문자는 반드시 숙지하길 바라며, 최소한 \n이 내려쓰기, \t는 탭이라는 것은 꼭! 외워놓기 바란다.

 Data를 가지고 오는 방법 중 txt data를 line별로 가지고 오거나, 탭을 구분자로 가져오는 경우가 많은데, 대상 Data 안에 해당 이스케이프 문자가 들어 있다면(예를 들어 URL Log Data), 데이터를 잘못 불러오는 문제가 발생할 수 있다.

 다음 포스트에선 자동으로 문자열의 일부를 바꾸는 방법인 포맷팅(Formating)에 대해 학습해보겠다. 

 

728x90
반응형

+ Recent posts