문자열과 텍스트 (Strings and Text)

서론

문자열은 텍스트를 위한 데이터 타입일 뿐입니다. 지금까지 여러분은 자세한 내용을 배우지 않은 채로 문자열을 사용해 왔습니다. 이제 문자열의 내부를 파헤쳐보고, 문자열을 다루는 강력한 도구들을 마스터할 시간입니다.

이 장은 Python String Cook Book과 Jake VanderPlas의 Python Data Science Handbook의 도움을 받았습니다.

문자열을 다루는 더 강력한 방법인 정규 표현식(regular expressions)이 있지만, 이는 다른 장에서 다루게 될 것입니다.

문자열 생성하기

앞서 책의 전반부에서 문자열을 만들어 보았지만 세부 사항은 논의하지 않았습니다. 먼저, 작은따옴표(')나 큰따옴표(") 중 하나를 사용하여 문자열을 만들 수 있습니다. 어느 쪽을 사용하든 상관없지만 일관성을 유지하는 것이 좋으며, 자동 코드 포맷터들은 대개 "를 선호합니다. 문자열 내부에 따옴표가 있는 경우 외부에는 다른 따옴표를 사용하세요.

코드 보기
string_one = "이것은 문자열입니다"
string_two = "문자열 안에 '따옴표'를 포함하고 싶다면, 바깥쪽에는 큰따옴표를 사용합니다"

문자열은 str 타입입니다:

코드 보기
type(string_one)
str

파이썬의 문자열은 인덱싱(indexing)이 가능하므로, 대괄호를 사용하여 원하는 위치의 특정 문자들을 가져올 수 있습니다.

코드 보기
var = "banana"
코드 보기
var[:3]
'ban'

리스트에 적용되는 일반적인 슬라이싱 기법들이 문자열에도 동일하게 적용됩니다. 즉, var[start:stop:step] 구문을 사용하여 원하는 위치의 문자들을 가져올 수 있습니다. 다음은 문자열의 두 번째 위치부터 시작하여 매 두 번째 문자마다 가져오는 예제입니다.

코드 보기
var[1::2]
'aaa'

문자열은 (1, 2, 3)과 같은 튜플과 마찬가지로(리스트 [1, 2, 3]와는 다르게) 불변(immutable)이라는 점에 유의하세요. 이는 var[0] = "B"와 같은 명령어는 에러를 발생시킨다는 의미입니다. 단일 문자를 변경하려면 전체 문자열을 교체해야 합니다. 이 예제에서 그 명령어는 var = "Banana"가 될 것입니다.

리스트와 마찬가지로 len()을 사용하여 문자열의 길이를 찾을 수 있습니다:

코드 보기
len(var)
6

+ 연산자를 사용하여 문자열을 이어 붙일 수 있습니다:

코드 보기
string_one + ". " + string_two + "."
"이것은 문자열입니다. 문자열 안에 '따옴표'를 포함하고 싶다면, 바깥쪽에는 큰따옴표를 사용합니다."

문장이 자연스럽게 이어지도록 추가 문자를 더한 것에 주목하세요. 리스트에 담긴 수많은 단어나 구절을 더 효율적으로 결합하는 또 다른 방법은 다음과 같습니다:

코드 보기
". ".join([string_one, string_two])
"이것은 문자열입니다. 문자열 안에 '따옴표'를 포함하고 싶다면, 바깥쪽에는 큰따옴표를 사용합니다"

알아두면 유용한 세 가지 함수로 upper(), lower(), title()이 있습니다. 이것들이 무엇을 하는지 보겠습니다.

코드 보기
var = "input TEXT"
var_list = [var.upper(), var.lower(), var.title()]
print(var_list)
['INPUT TEXT', 'input text', 'Input Text']

파이썬에는 문자열을 사용하기 위한 수많은 내장 함수가 있습니다. 전체 목록은 여기에서 확인할 수 있습니다.

{.callout-note} 연습 문제 인덱싱 연산을 사용하여 문자열 `"gnirts desrever a si sihT"`를 뒤집어 보세요.

print() 함수에는 몇 가지 요령이 있습니다. 리스트가 있다면 주어진 구분자와 함께 항목들을 출력할 수 있습니다:

코드 보기
print(*var_list, sep="; and \n")
INPUT TEXT; and 
input text; and 
Input Text

(곧 ’’이 무엇을 하는지 알아보겠습니다.) 다른 종류의 변수를 문자열로 바꾸려면 str() 함수를 사용하세요. 예:

코드 보기
(
    "불리언은 "
    + str(True)
    + " 또는 "
    + str(False)
    + " 중 하나이며, 오직 "
    + str(2)
    + "가지 옵션만 있습니다."
)
'불리언은 True 또는 False 중 하나이며, 오직 2가지 옵션만 있습니다.'

이 예제에서는 두 개의 불리언 변수와 하나의 정수 변수가 문자열로 변환되었습니다. str()은 대개 문자열이 아닌 변수를 어떻게 문자열 타입으로 변환하고 싶어 하는지 지능적으로 추측합니다. 변수나 리터럴 값을 str()에 전달할 수 있습니다.

f-문자열 (f-strings)

위의 예제는 상당히 장황합니다. 문자열과 변수를 결합하는 또 다른 방법은 f-문자열을 통하는 것입니다. 간단한 f-문자열은 다음과 같습니다:

코드 보기
variable = 15.32399
print(f"획득한 점수: {variable}")
획득한 점수: 15.32399

이는 변수에 str을 호출하고 연결을 위해 +를 사용하는 것과 비슷하지만 훨씬 짧게 쓸 수 있습니다. f-문자열에 표현식을 추가할 수도 있습니다:

코드 보기
print(f"획득한 점수의 제곱: {variable**2}")
획득한 점수의 제곱: 234.8246695201

이 방식은 함수와도 작동합니다. 결국 **2도 자체적인 특수 구문을 가진 함수일 뿐이니까요.

이 예제에서 출력된 점수에는 (아마도) 흥미롭지 않은 소수점이 많이 포함되어 있었습니다. 그렇다면 출력물을 어떻게 다듬을 수 있을까요? f-문자열에 더 많은 정보를 전달하여 원하는 대로 서식을 지정할 수 있습니다. 소수점 둘째 자리와 부호를 원한다고 가정해 봅시다 (형식에는 항상 +를 쓰지만, 실제 값에 따라 + 또는 -로 출력됩니다):

코드 보기
print(f"획득한 점수: {variable:+.2f}")
획득한 점수: +15.32

다음 표와 같이 숫자를 위한 다양한 서식 옵션들이 있습니다.

숫자 서식 출력 설명
15.32347 {:.2f} 15.32 실수 소수점 2자리 서식
15.32347 {:+.2f} +15.32 부호 포함 실수 소수점 2자리 서식
-1 {:+.2f} -1.00 부호 포함 실수 소수점 2자리 서식
15.32347 {:.0f} 15 소수점 없는 실수 서식
3 {:0>2d} 03 0으로 채우기 (왼쪽 패딩, 너비 2)
3 {:*<4d} 3*** *로 채우기 (오른쪽 패딩, 너비 4)
13 {:*<4d} 13** *로 채우기 (오른쪽 패딩, 너비 4)
1000000 {:,} 1,000,000 천 단위 콤마 구분자 서식
0.25 {:.1%} 25.0% 백분율 서식
1000000000 {:.2e} 1.00e+09 지수 표기법
12 {:10d}            12 우측 정렬 (기본값, 너비 10)
12 {:<10d} 12             좌측 정렬 (너비 10)
12 {:^10d}      12        중앙 정렬 (너비 10)

상단의 Colab이나 Binder 링크를 통해 이 페이지를 대화형으로 사용하거나 컴퓨터로 다운로드하여 사용하는 것 외에도, 이 링크에서 이러한 옵션들을 가지고 놀아볼 수 있습니다.

특수 문자와 문자열 이스케이프 방법

파이썬에는 유용한 내장 문자열과 문자들을 제공하는 string 모듈이 있습니다. 예를 들어

코드 보기
import string

string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

은 모든 구두점을 제공하며,

코드 보기
string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

는 ‘ASCII’ 인코딩의 모든 기본 알파벳 문자들(.ascii_lowercase.ascii_uppercase 변형 포함)을 반환하고,

코드 보기
string.digits
'0123456789'

은 0부터 9까지의 숫자를 제공합니다. 마지막으로 시각적으로는 덜 인상적이지만, string.whitespace는 모든 유형의 공백(한 가지 종류가 아닙니다!)을 포함하는 문자열을 제공합니다.

다른 특수 문자들도 있습니다. 사실 우리는 이미 그중 가장 유명한 것을 만났습니다: 줄바꿈을 뜻하는 “”입니다. 실제로 “”을 출력하려면 백슬래시 앞에 백슬래시를 하나 더 추가하여 백슬래시를 ’이스케이프(escape)’해야 합니다.

코드 보기
print("여기에 \n 줄바꿈이 있습니다")
print("여기에 이스케이프된 \\n 줄바꿈 표시가 있습니다 ")
여기에 
 줄바꿈이 있습니다
여기에 이스케이프된 \n 줄바꿈 표시가 있습니다 

아래 표는 가장 중요한 이스케이프 명령어를 보여줍니다:

코드 결과
\' 작은따옴표 (문자열에 '를 사용할 때 유용)
\" 큰따옴표 (문자열에 "를 사용할 때 유용)
\\ 백슬래시
\n 줄바꿈 (New Line)
\r 캐리지 리턴 (Carriage Return)
\t 탭 (Tab)

더 복잡한 예제입니다:

코드 보기
print("a\tb\nA\tB")
a   b
A   B

원시 문자열 (Raw Strings)

r 접두사가 붙은 문자열(예: r’…’ 및 r”…“)은 원시 문자열이라고 하며 백슬래시 특수 문자가 아닌 일반 문자로 취급합니다.

코드 보기
print(r"a\tb\nA\tB")
a\tb\nA\tB

텍스트 정리하기 (Cleaning Text)

사용 중인 텍스트를 변경하고 싶을 때가 많습니다. 이 섹션에서는 이를 위한 다양한 옵션들을 살펴보겠습니다.

부분 문자열 교체하기

일반적인 텍스트 작업은 긴 문자열 내의 부분 문자열(substring)을 교체하는 것입니다. 문자열 변수 var가 있다고 해봅시다. .replace(old_text, new_text)를 사용하여 이를 수행할 수 있습니다.

코드 보기
"Value is objective".replace("objective", "subjective")
'Value is subjective'

특정 타입(여기서는 문자열)의 모든 변수와 마찬가지로, 이 방식은 변수와도 잘 작동합니다:

코드 보기
text = "Value is objective"
old_substr = "objective"
new_substr = "subjective"
text.replace(old_substr, new_substr)
'Value is subjective'

.replace()는 정확히 일치하는 텍스트를 교체하므로 대소문자를 구분한다는 점에 유의하세요.

translate를 사용하여 문자 교체하기

문자(character)는 ’equilibrium’의 ’l’과 같이 문자열 내의 개별 항목입니다. len(var)를 사용하여 문자열 변수 var의 문자 수를 언제든지 셀 수 있습니다. 문자열의 개별 문자를 교체하는 매우 빠른 방법은 str.translate()입니다.

문자 교체는 특정 상황에서 매우 유용한데, 가장 흔한 경우는 다른 텍스트 분석을 수행하기 전에 모든 구두점을 제거하고 싶을 때입니다. 이를 위해 내장된 string.punctuation을 사용할 수 있습니다.

텍스트에서 모든 모음을 제거하는 데 어떻게 사용하는지 보겠습니다. 경제학자 리사 쿡(Lisa Cook)에게는 미안하지만, (cook2011inventing에서?) 발췌한 초록을 우리가 수정할 텍스트로 사용하겠습니다. 먼저 모음을 빈 문자열인 ""로 바꾸는 번역 딕셔너리를 만들겠습니다.

코드 보기
example_text = "Much recent work has focused on the influence of social capital on innovative outcomes. Little research has been done on disadvantaged groups who were often restricted from participation in social networks that provide information necessary for invention and innovation. Unique new data on African American inventors and patentees between 1843 and 1930 permit an empirical investigation of the relation between social capital and economic outcomes. I find that African Americans used both traditional, i.e., occupation-based, and nontraditional, i.e., civic, networks to maximize inventive output and that laws constraining social-capital formation are most negatively correlated with economically important inventive activity."
vowels = "aeiou"
translation_dict = {x: "" for x in vowels}
translation_dict
{'a': '', 'e': '', 'i': '', 'o': '', 'u': ''}

이제 딕셔너리를 문자열 번역기로 변환하여 텍스트에 적용합니다:

코드 보기
translator = example_text.maketrans(translation_dict)
example_text.translate(translator)
'Mch rcnt wrk hs fcsd n th nflnc f scl cptl n nnvtv tcms. Lttl rsrch hs bn dn n dsdvntgd grps wh wr ftn rstrctd frm prtcptn n scl ntwrks tht prvd nfrmtn ncssry fr nvntn nd nnvtn. Unq nw dt n Afrcn Amrcn nvntrs nd ptnts btwn 1843 nd 1930 prmt n mprcl nvstgtn f th rltn btwn scl cptl nd cnmc tcms. I fnd tht Afrcn Amrcns sd bth trdtnl, .., ccptn-bsd, nd nntrdtnl, .., cvc, ntwrks t mxmz nvntv tpt nd tht lws cnstrnng scl-cptl frmtn r mst ngtvly crrltd wth cnmclly mprtnt nvntv ctvty.'

{.callout-note} 연습 문제 `translate`를 사용하여 다음 문장의 모든 구두점을 공백으로 바꿔보세요: "The well-known story I told at the conferences [about hypocondria] in Boston, New York, Philadelphia,...and Richmond went as follows: It amused people who knew Tommy to hear this; however, it distressed Suzi when Tommy (1982--2019) asked, \"How can I find out who yelled, 'Fire!' in the theater?\" and then didn't wait to hear Missy give the answer---'Dick Tracy.'"

일반적으로 str.translate는 문자열의 개별 문자를 교체하는 데 매우 빠릅니다. 하지만 다음과 같이 리스트 컴프리헨션과 결과 리스트의 join()을 사용하여 수행할 수도 있습니다:

코드 보기
"".join(
    [
        ch
        for ch in "Example. string. with- excess_ [punctuation]/,"
        if ch not in string.punctuation
    ]
)
'Example string with excess punctuation'

문자열 분할하기 (Splitting strings)

문자열을 특정 위치에서 분할하고 싶다면 두 가지 빠른 방법이 있습니다. 첫 번째는 인덱싱 방법을 사용하는 것으로, 텍스트를 분할할 위치를 알고 있을 때 잘 작동합니다. 예:

코드 보기
"This is a sentence and we will split it at character 18"[:18]
'This is a sentence'

다음으로 내장된 split() 함수를 사용할 수 있는데, 이 함수는 주어진 부분 문자열이 나타나는 위치의 리스트를 반환합니다:

코드 보기
"This is a sentence. And another sentence. And a third sentence".split(".")
['This is a sentence', ' And another sentence', ' And a third sentence']

문자열을 분할하는 데 사용된 문자는 결과 문자열 리스트에서 제거된다는 점에 유의하세요. 단일 문자가 아닌 문자열을 분할 기준으로 사용하는 예제를 보겠습니다:

코드 보기
"This is a sentence. And another sentence. And a third sentence".split("sentence")
['This is a ', '. And another ', '. And a third ', '']

유용한 추가 함수로 splitlines()가 있는데, 이는 줄바꿈 위치에서 문자열을 분할하고 분할된 부분을 리스트로 반환합니다.

count와 find

str.count()를 사용하여 텍스트 내의 단어 빈도를 간단히 계산해 보겠습니다. 엘리자베스 비숍(Elizabeth Bishop)의 세스티나 ’A Miracle for Breakfast’의 첫 연을 예제 텍스트로 사용하겠습니다.

코드 보기
text = "At six o'clock we were waiting for coffee, \n waiting for coffee and the charitable crumb \n that was going to be served from a certain balcony \n --like kings of old, or like a miracle. \n It was still dark. One foot of the sun \n steadied itself on a long ripple in the river."
word = "coffee"
print(f'"{word}"라는 단어는 {text.count(word)}번 나타납니다.')
"coffee"라는 단어는 2번 나타납니다.

한편, find()는 특정 단어나 문자가 처음으로 나타나는 위치를 반환합니다.

코드 보기
text.find(word)
35

반환된 숫자와 문자열 인덱싱을 사용하여 이를 확인할 수 있습니다:

코드 보기
text[text.find(word) : text.find(word) + len(word)]
'coffee'

하지만 이 텍스트에서 ’coffee’라는 단어가 한 번만 나타나는 것은 아닙니다. 마지막 발생 위치를 찾으려면 다음과 같이 합니다.

코드 보기
text.rfind(word)
57

여러 문자열 다루기

개별 문자열로 작업하는 방법을 보았습니다. 하지만 흔히 우리는 말뭉치(corpus), 즉 텍스트 모음이라 불리는 일련의 문자열 그룹으로 작업하고 싶어 합니다. 단어, 문장, 단락 또는 도메인 기반의 그룹화(예: 채용 공고)가 될 수 있습니다. 다른 파이썬 객체와 마찬가지로 문자열들을 리스트(또는 다른 반복 가능한 객체)에 넣을 수 있습니다.

그리고 다행히도 단일 문자열에 대해 수행했던 많은 메서드를 pandas나 다른 도구들을 사용하여 수백, 수천, 수백만 개의 문자열로 쉽게 확장할 수 있습니다. 이러한 확장은 단일 값(스칼라)에서 리스트 내의 여러 값(벡터)으로 넘어가는 것과 유사하게 벡터화(vectorisation)를 통해 이루어집니다.

아주 작은 예로, 리스트 컴프리헨션을 사용하여 이름의 첫 글자를 대문자로 만드는 벡터화 작업을 보겠습니다:

코드 보기
[name.capitalize() for name in ["ada", "adam", "elinor", "grace", "jean"]]
['Ada', 'Adam', 'Elinor', 'Grace', 'Jean']

리스트 대신 pandas 시리즈(series)를 사용할 수도 있습니다. 먼저 시리즈를 만들어 보겠습니다:

코드 보기
import pandas as pd

dfs = pd.Series(
    ["ada lovelace", "adam smith", "elinor ostrom", "grace hopper", "jean bartik"],
    dtype="string",
)
dfs
0     ada lovelace
1       adam smith
2    elinor ostrom
3     grace hopper
4      jean bartik
dtype: string

이제 series.str.function 구문을 사용하여 텍스트 시리즈를 변경합니다:

코드 보기
dfs.str.title()
0     Ada Lovelace
1       Adam Smith
2    Elinor Ostrom
3     Grace Hopper
4      Jean Bartik
dtype: string

시리즈가 아니라 데이터 프레임이라면, 다음과 같이 관심 있는 열을 지정하도록 구문이 바뀝니다.

코드 보기
df = pd.DataFrame(dfs, columns=["names"])
df["names"].str.title()
0     Ada Lovelace
1       Adam Smith
2    Elinor Ostrom
3     Grace Hopper
4      Jean Bartik
Name: names, dtype: string

아래 표는 pandas에서 사용할 수 있는 문자열 메서드들의 일부 목록입니다.

함수 (.str.으로 시작) 기능
len() 문자열의 길이.
lower() 소문자로 변환.
upper() 대문자로 변환.
capitalize() 첫 글자만 대문자로 변환.
swapcase() 대소문자 반전.
translate() 주어진 번역 테이블을 통해 각 문자가 매핑된 복사본을 반환.
ljust() 좌측 패딩 (기본값은 공백 채우기)
rjust() 우측 패딩 (기본값은 공백 채우기)
center() 중앙 패딩 (기본값은 공백 채우기)
zfill() 0으로 채우기
strip() 앞뒤 공백 제거
rstrip() 뒤쪽 공백 제거
lstrip() 앞쪽 공백 제거
find() 부분 문자열이 나타나는 데이터 내의 최저 인덱스 반환
split() 전달된 부분 문자열을 구분자로 사용하여 문자열 분할
isupper() 대문자인지 확인
isdigit() 숫자로만 구성되었는지 확인
islower() 소문자인지 확인
startswith() 주어진 부분 문자열로 시작하는지 확인

정규 표현식 또한 pandas를 통해 확장될 수 있습니다. 아래 표는 벡터화된 정규 표현식을 보여줍니다.

함수 기능
match() 각 요소에 re.match()를 호출하여 불리언 반환.
extract() 각 요소에 re.match()를 호출하여 매칭된 그룹을 문자열로 반환.
findall() 각 요소에 re.findall() 호출
replace() 패턴의 발생을 다른 문자열로 교체
contains() 각 요소에 re.search()를 호출하여 불리언 반환
count() 패턴의 발생 횟수 계산
split() str.split()과 동일하지만 정규 표현식을 허용함
rsplit() str.rsplit()과 동일하지만 정규 표현식을 허용함

이들 중 몇 가지를 직접 확인해 보겠습니다. 먼저 주어진 부분 문자열을 기준으로 분할하는 예제입니다:

코드 보기
df["names"].str.split(" ")
0     [ada, lovelace]
1       [adam, smith]
2    [elinor, ostrom]
3     [grace, hopper]
4      [jean, bartik]
Name: names, dtype: object

문자열을 분할하고 그 결과를 데이터 프레임의 새로운 열로 저장하고 싶은 경우가 매우 흔합니다. n= 인수를 통해 최대 분할 횟수를 지정할 수 있고, expand를 사용하여 열을 얻을 수 있습니다.

코드 보기
df["names"].str.split(" ", n=2, expand=True)
0 1
0 ada lovelace
1 adam smith
2 elinor ostrom
3 grace hopper
4 jean bartik

{.callout-note} 연습 문제 벡터화된 연산을 사용하여, `names` 열의 각 행에서 첫 번째 모음이 나타나는 인덱스 위치가 담긴 새로운 열을 만들어 보세요.

다음은 pandas에서 정규 표현식 함수를 사용하는 예제입니다:

코드 보기
df["names"].str.extract("(\w+)", expand=False)
0       ada
1      adam
2    elinor
3     grace
4      jean
Name: names, dtype: string

유용한 몇 가지 벡터화된 문자열 연산들이 더 있습니다.

메서드 설명
get() 각 요소 인덱싱
slice() 각 요소 슬라이싱
slice_replace() 각 요소의 슬라이스를 전달된 값으로 교체
cat() 문자열 이어 붙이기
repeat() 값 반복
normalize() 유니코드 형식 문자열 반환
pad() 문자열의 왼쪽, 오른쪽 또는 양쪽 모두에 공백 추가
wrap() 긴 문자열을 지정된 너비 미만의 줄들로 분할
join() 각 요소의 문자열을 전달된 구분자로 결합
get_dummies() 더미 변수들을 데이터 프레임으로 추출

get()slice() 메서드는 split()에 의해 반환된 리스트의 요소에 접근할 수 있게 해줍니다. split()get()을 결합한 예제입니다:

코드 보기
df["names"].str.split().str.get(-1)
0    lovelace
1       smith
2      ostrom
3      hopper
4      bartik
Name: names, dtype: object

기호로 구분된 태그가 포함된 열이 있다면, get_dummies() 함수를 사용하여 이를 분리할 수 있습니다. 예를 들어 과목과 국적 태그가 섞여 있는 단일 열을 가진 데이터 프레임을 만들어 보겠습니다:

코드 보기
df = pd.DataFrame(
    {
        "names": [
            "ada lovelace",
            "adam smith",
            "elinor ostrom",
            "grace hopper",
            "jean bartik",
        ],
        "tags": ["uk; cs", "uk; econ", "usa; econ", "usa; cs", "usa; cs"],
    }
)
df
names tags
0 ada lovelace uk; cs
1 adam smith uk; econ
2 elinor ostrom usa; econ
3 grace hopper usa; cs
4 jean bartik usa; cs

이제 str.get_dummies()를 사용하고 ;로 분할하면 더미들로 구성된 데이터 프레임을 얻을 수 있습니다.

코드 보기
df["tags"].str.get_dummies(";")
cs econ uk usa
0 1 0 1 0
1 0 1 1 0
2 0 1 0 1
3 1 0 0 1
4 1 0 0 1

텍스트 읽어오기

텍스트 파일

단순히 평범한 텍스트 파일만 있다면 다음과 같이 읽어올 수 있습니다:

fname = 'book.txt'
with open(fname, encoding='utf-8') as f:
    text_of_book = f.read()

또한 다음과 같이 pandas 데이터 프레임으로 직접 텍스트 파일을 읽어올 수도 있습니다.

df = pd.read_csv('book.txt', delimiter = "\n")

위의 경우 데이터 프레임의 각 행을 구분하는 구분자(delimiter)가 줄바꿈인 “”으로 설정되었지만, 선호하는 어떤 구분자든 사용할 수 있습니다.

{.callout-note} 연습 문제 [이 링크](https://github.com/aeturrell/coding-for-economists/blob/main/data/smith_won.txt)를 사용하여 'smith_won.txt' 파일을 다운로드하세요(우클릭 후 다른 이름으로 저장 사용). 그런 다음 **pandas**를 사용하여 텍스트를 읽어오세요.

CSV 파일

CSV 파일은 이미 행으로 나뉘어 있습니다. CSV 파일을 읽는 가장 쉬운 방법은 pandas를 사용하는 것입니다.

df = pd.read_csv('book.csv')

pandas는 다른 많은 파일 형식도 읽을 수 있다는 점을 기억하세요.