파이썬-pandas-데이터-프레임-판다1
데이터를 구해보자.

지난 시간에는 pandas Series 사용법을 알아보았습니다. Python pandas에서 시리즈(Series)가 1차원 자료 구조라면 데이터 프레임(DataFrame)은 2차원 자료 구조입니다. 2차원이라는 뜻은 자료 구조가 표 같은 스프레드시트 형식처럼 행과 열로 되어있다는 의미입니다.

pandas(판다스)의 DataFrame의 여러 열에는 서로 다른 종류의 값(숫자, 문자열, 불리언 등)을 담을 수 있습니다. 그리고 행 색인(row indices)과 열 색인(column indices)에 각각 행 이름과 열 이름을 붙일 수도 있죠. 이번 시간에는 데이터를 준비하는 1단계를 알아보겠습니다. 바로 DataFrame을 만들고, DataFrame을 만들기 위해 데이터를 로딩하며, 색인(index)을 관리하는 일입니다. 그럼 Python pandas 사용법, 함께 익혀볼까요?

생성하기(Creating)

pandas의 DataFrame을 만드는 클래스는 pandas.DataFrame입니다. DataFrame 클래스는 data, index, columns를 매개변수로 갖습니다. 각 매개변수는 순서대로 데이터, 행색인(row index), 열색인(column index)을 의미합니다.

python
pandas.DataFrame(data, index, columns)

DataFrame은 사전(dictionary), 리스트(list), 배열(array), Series 등 다양한 자료구조로 만들 수 있습니다. 먼저 사전형 자료구조로 DataFrame을 만드는 법부터 알아보겠습니다.

사전

pandas에서 DataFrame을 만들 때 가장 많이 사용하는 자료구조는 리스트를 값으로 가지는 사전입니다.

리스트를 값으로 갖는 사전

리스트를 값으로 갖는 사전이란 사전의 키에 해당하는 값이 리스트인 자료구조를 말합니다. 리스트를 값으로 갖는 사전으로 DataFrame을 만드는 예시 코드는 다음과 같습니다.

python
data_dict = {'백신': ['아스트라제네카', '화이자', '모더나', '얀센', '노바'],
'재고': [100, 200, 300, 400, 500]}
df = pd.DataFrame(data_dict,
index=[x for x in 'abcde']) # 행색인 지정
df
리스트를 값으로 갖는 사전으로 만든 DataFrame
리스트를 값으로 갖는 사전으로 만든 DataFrame  - Snug Archive

사전을 값으로 갖는 사전

사전을 값으로 갖는 사전이란 사전 안에 사전이 있는 자료구조를 말합니다. 이를 중첩 사전(nested dictionary)이라고 합니다. 중첩된 사전을 입력 데이터로 사용할 때는 바깥에 있는 사전의 키가 열 색인이 되고 안에 있는 키가 행 색인이 됩니다.

python
data_dict = {'수면시간': {'1번': 7, '2번': 3, '3번': 6},
'생산성': {'1번': 8, '2번': 4, '3번': 5}}
df = pd.DataFrame(data_dict)
df
중첩사전으로 만든 DataFrame
중첩사전으로 만든 DataFrame  - Snug Archive

Series를 값으로 갖는 사전

Series를 값으로 갖는 사전으로 DataFrame을 만들 수도 있습니다. Series를 값으로 갖는 사전을 DataFrame으로 만드는 예시 코드는 다음과 같습니다.

python
data_dict = {'A조': pd.Series([1, 2, 3, 4, 5],
index=[f'{x+1}번' for x in range(5)]),
'B조': pd.Series([1, 2, 3, 4, 5],
index=[f'{x+1}번' for x in range(5)])}
df = pd.DataFrame(data_dict)
df
Series를 값으로 갖는 사전으로 만든 DataFrame
Series를 값으로 갖는 사전으로 만든 DataFrame  - Snug Archive

슬라이싱(slicing)으로 가져온 DataFrame의 열로도 DataFrame을 만들 수 있습니다. 슬라이싱은

에서 자세히 다루겠습니다.

python
data_selected = {'A': df['A조'][:-1], # 1행부터 마지막 행 전까지
'B': df['B조'][:2]} # 1행부터 2행까지
df = pd.DataFrame(data_selected)
df
Series를 값으로 갖는 사전으로 만든 DataFrame2
Series를 값으로 갖는 사전으로 만든 DataFrame2  - Snug Archive

배열(array)과 튜플(tuples)을 값으로 갖는 사전도 이와 동일한 방식으로 만들면 됩니다. 지금까지 사전형 자료구조로 DataFrame을 만드는 법을 알아보았습니다. 이번에는 리스트로 DataFrame을 만드는 법을 살펴보겠습니다.

리스트

1개의 1차원 리스트

1차원 리스트로 DataFrame을 만드는 예시 코드는 다음과 같습니다.

python
data_1dlist = [1, 2, 3, 4, 5] # 1차원 리스트
df = pd.DataFrame(data_1dlist, columns=['숫자']) # 열이름 지정
df
1개의 1차원 리스트로 만든 DataFrame
1개의 1차원 리스트로 만든 DataFrame  - Snug Archive

여러 개의 1차원 리스트

여러 개의 1차원 리스트를 이용해 DataFrame을 만들고 싶다면 zip 함수를 이용하면 됩니다. 이 함수는 한 리스트의 개별 원소를 다른 리스트의 개별 원소와 순서대로 맵핑해줍니다. 여러 개의 1차원 리스트를 이용해 DataFrame을 만드는 예시 코드는 아래와 같습니다.

python
vegetables = ['사과', '당근', '케일', '토마토', '배추']
stocks = [1, 2, 3, 4, 5]
ranks = [5, 2, 4, 1, 3]
list_of_tuples = list(zip(vegetables, stocks, ranks)) # 튜플로 이루어진 리스트 생성
df = pd.DataFrame(list_of_tuples,
columns=['상품', '재고', '순위'])
df
여러 개의 1차원 리스트로 만든 DataFrame
여러 개의 1차원 리스트로 만든 DataFrame  - Snug Archive

2차원 리스트

2차원 리스트는 리스트 안에 리스트(list of lists)가 있는 자료 구조를 말합니다. 2차원 리스트로 DataFrame을 만드는 구조는 다음과 같습니다.

python
data_2dlist = [['사과', 2], ['딸기', 5], ['수박', 1]]
df = pd.DataFrame(data_2dlist, columns=['과일명', '수량']) # 열이름 지정
df
2차원 리스트로 만든 DataFrame
2차원 리스트로 만든 DataFrame  - Snug Archive

사전으로 이루어진 리스트

사전을 원소로 갖는 리스트(list of dictionary)는 리스트의 원소가 사전인 자료구조입니다. 사전으로 이루어진 리스트로 DataFrame을 만들면 사전의 키는 열 이름이 되고 값이 각 행에 입력됩니다.

python
data = [{'개': '멍멍', '고양이': '야옹', '오리': '꽥꽥'},
{'개': 5, '고양이': 3, '오리': 4}]
df = pd.DataFrame(data)
df
사전을 원소로 갖는 리스트로 만든 DataFrame
사전을 원소로 갖는 리스트로 만든 DataFrame  - Snug Archive

만약 기존 데이터에 없는 키를 열 이름으로 지정하면 해당 열에 있는 모든 값은 NaN이 됩니다.

python
data = [{'강아지': '멍멍', '고양이': '야옹', '오리': '꽥꽥'},
{'강아지': 5, '고양이': 3, '오리': 4}]
df = pd.DataFrame(data, index=['1번', '2번'], columns=['강아지', '고양이', '새'])
df
키와 열이름이 일치하지 않을 때 값이 NaN으로 처리되는 DataFrame
키와 열이름이 일치하지 않을 때 값이 NaN으로 처리되는 DataFrame  - Snug Archive

배열

Numpy의 배열로 DataFrame을 만드는 방법도 리스트를 이용해서 DataFrame을 만드는 방법과 동일합니다.

python
data_arr = np.array([[100, 50, 70, 90], [10, 20, 30, 40]])
df = pd.DataFrame(data_arr)
df
배열로 만든 DataFrame
배열로 만든 DataFrame  - Snug Archive

Series

Series로도 DataFrame으로 만들 수 있습니다.

python
data_ser = pd.Series([1, 2, 3, 4, 5])
df = pd.DataFrame(data_ser)
df
Series로 만든 DataFrame
Series로 만든 DataFrame  - Snug Archive

지금까지 사전, 리스트, 배열, Series 등 다양한 자료구조로 DataFrame을 만드는 법을 알아보았습니다. DataFrame을 직접 만들지 않고 다른 곳에서 가져와서 사용할 수도 있습니다. 파일을 DataFrame 객체 형식으로 읽어오는 것입니다. 이번에는 데이터를 로딩(loading)해서 DataFrame 객체로 읽어오는 방법을 알아보겠습니다. 만든 DataFrame 이나 불러온 DataFrame을 다시 파일로 저장(saving)하는 법도 함께 알아보겠습니다.

로딩하고 저장하기(Loading and Saving)

pandas에서 DataFrame 객체로 읽어올 수 있는 대상은 텍스트 파일, 웹 API, 데이터베이스(database)가 있습니다. 여기서는 텍스트 파일(.csv, .xlsx, *.txt 등)을 로딩하고 저장하는 법을 살펴보겠습니다. 웹 API를 이용해서 데이터를 가져오는 방법은 파이썬 웹 크롤링? 웹 스크래핑 개념과 실습 예제를 참조해주세요.

1) CSV 파일: read_csv / to_csv

CSV(Comma-Separated Values)는 쉼표(,)를 구분자(separator)로 갖는 텍스트 파일입니다. pandas에서 CSV 파일을 가져오고 싶을 때는 read_csv함수를 사용하면 됩니다.

python
df = pd.read_csv('data.csv') # 읽어올 파일 경로 + 파일명 + 확장자 입력

만약 만든 Series 또는 DataFrame을 CSV 파일 형식으로 저장하고 싶다면 to_csv 함수를 이용하면 됩니다. 특히, 한글로 된 CSV 파일을 저장할 때는 encoding='utf-8-sig' 옵션을 주는 것이 좋습니다. 인코딩을 이 방식으로 하면 한글이 깨지는 현상을 방지할 수 있습니다. 또한, index=False 옵션을 주면 인덱스를 따로 생성하지 않고 저장할 수 있습니다.

python
pd.to_csv('data.csv', # 저장할 파일 경로 + 파일명 + 확장자 입력
encoding='utf-8-sig', # 한글 파일 깨짐 방지
index=False) # 인덱스 번호를 따로 생성하지 않기

read_csv 함수 인자에는 50개 이상의 옵션이 있습니다. to_csv 함수 인자에도 20개 이상의 옵션이 있습니다. 모든 옵션은 pandas 공식 홈페이지 pandas.read_csvpandas 공식 홈페이지 pandas.to_csv에서 확인하실 수 있습니다. 여기서는 read_csv의 옵션 중에서 자주 사용하는 옵션만 살펴보겠습니다.

인코딩 설정하기: encoding

앞서 to_csv의 파라미터에서 살펴보았듯 encoding 옵션은 유니코드(Unicode)의 인코딩 종류를 지정합니다. 한글의 경우 인코딩 방식으로 utf-8-sig를 지정하면 한글이 깨지는 현상 없이 파일을 잘 불러올 수 있습니다.

python
df = pd.read_csv('data.csv', encoding='utf-8-sig')

헤더 설정하기: header

header는 헤더(header)로 사용할 행을 지정하는 옵션입니다. 헤더는 열 이름이 있는 행을 말합니다. header의 값에는 열이름이 있는 행의 인덱스를 입력하면 됩니다. 예를 들어, 불러오고 싶은 파일에서 컬럼명이 있는 행이 두 번째 행에 있다면 header=1을 사용하면 됩니다. 만약 파일에 열 이름이 없다면(데이터 레코드로 바로 시작한다면) 옵션에 None을 전달하면 됩니다. 코드는 다음과 같습니다.

python
df = pd.read_csv('data.csv', header=0) # 읽어올 CSV 파일에서 컬럼명이 첫 번째 행에 위치함
df = pd.read_csv('data.csv', header=None) # 헤더 지정 안하고 데이터 가져오기

만약 첫 번째 행과 두 번째 행을 모두 열색인으로 지정하고 싶다면 header 값으로 열색인으로 만들고 싶은 행의 인덱스가 담긴 리스트를 주면 됩니다.

python
df = pd.read_csv('data.csv', header=[0, 1]) # 1행과 2행 지정

열 이름 지정하기: names

열의 이름을 지정하고 싶다면 names 옵션을 사용하면 됩니다. 예를 들어 각 열에 순서대로 '가', '나', '다', '라'라는 이름을 붙이고 싶다면, 아래와 같이 names 옵션에 이 값을 담은 리스트를 할당하면 됩니다.

python
df = pd.read_csv('data.csv', names=['가', '나', '다', '라']) # 열 이름 지정하기

행색인 지정하기: index_col

특정 열을 행색인으로 지정하고 싶다면 index_col 옵션을 사용하면 됩니다. 다음 코드는 '강수량'이라는 이름의 열을 행색인으로 지정합니다.

python
df = pd.read_csv('data.csv', index_col='강수량') # 행색인으로 사용할 열 지정

만약 계층적 색인(hierarchical index)을 만들고 싶다면 계층적 색인으로 만들고 싶은 열의 인덱스 또는 열 이름이 담긴 리스트를 index_col 옵션에 넘겨주면 됩니다.

python
df = pd.read_csv('data.csv',
index_col=['학교', '학년']) # 계층적 색인 지정: 학교별 학년별 자료

앞에서 행 건너뛰기: skiprows

특정 행을 건너뛰고 자료를 가져오고 싶다면 skiprows 옵션을 사용하면 됩니다. 옵션값으로는 건너뛰고 싶은 행의 개수를 입력하면 됩니다. 예를 들어 1개 행을 건너뛰고 2번째 행부터 데이터를 가져오고 싶다면 skiprows=1 옵션을 사용하면 됩니다(지정된 개수만큼 건너뜀).

python
df = pd.read_csv('data.csv', skiprows=2) # 2개 행 건너뛰고 3번째 행부터 가져오기

skiprows 옵션은 데이터의 열이름 있는 행이 첫 번째 행에 위치하지 않을 때 사용하면 됩니다. 만약 특정 행을 제외하고 데이터를 불러오고 싶다면 아래와 같이 이 옵션에 건너뛰고 싶은 행의 정수 색인을 담은 리스트를 할당하면 됩니다.

python
df = pd.read_csv('data.csv', skiprows=[0, 2, 4]) # 0행, 2행, 4행 빼고 데이터 가져오기

뒤에서 행 건너뛰기: skipfooter

skiprows와는 반대로 skipfooter는 데이터의 끝부분부터 몇 개의 행을 생략하고 데이터를 불러올 것인지를 지정하는 옵션입니다.

python
df = pd.read_csv('data.csv', skipfooter=2) # 마지막 행부터 총 2개 행 건너뛰고 데이터 가져옴

가져오고 싶은 행 개수 지정하기: nrows

nrows는 데이터의 첫 행부터 가져오고 싶은 행의 개수를 지정하는 옵션입니다. 이 옵션을 사용하면 처음부터 몇 번째 행까지 읽어올 것인지를 지정할 수 있습니다.

python
df = pd.read_csv('data.csv', nrows=3) # 자료가 시작하는 1행부터 총 3개 행 가져오기

다음과 같이 skiprowsnrows을 함께 쓸 수도 있습니다.

python
df = pd.read_csv('data.csv',
skiprows=2 # 처음 2개 행 무시하기
nrows=5) # 그 이후부터 5개 행 가져오기

불러오고 싶은 열 지정하기: usecols

자료에서 가져오고 싶은 열을 특정하고 싶다면 usecols 옵션을 사용하면 됩니다. 예제 코드는 다음과 같습니다.

python
df = pd.read_csv('data.csv', usecols=[0, 1]) # 0번째, 1번째 열만 가져오기
df = pd.read_csv('data.csv', usecols=['포켓몬명', '희망전공']) # 2개 열 가져오기

특정 열 1개를 제외하고 데이터를 가져오려면 lambda 함수를 사용하면 됩니다. 예시 코드는 다음과 같습니다.

python
df = pd.read_csv('data.csv', usecols=lambda x: x !='포켓몬명') # '포켓몬명' 열 제외

만약, 다수의 특정 열을 제외하고 데이터를 가져오고 싶다면 다음과 같은 코드를 사용하면 됩니다.

python
columns_to_skip = ['국어', '수학']
df = pd.read_csv('data.csv', usecols=lambda x: x not in columns_to_skip)

결측치 처리하기: na_values

na_values는 결측치를 처리하는 옵션입니다. 예를 들어, na_values=['없음'] 을 사용하면 결측치가 NaN 대신 '없음'으로 표기됩니다.

python
df = pd.read_csv('data.csv', na_values=['None']) # 결측치가 'None'으로 표기됨

다음으로는 엑셀 파일을 로딩하고 저장하는 법을 알아보겠습니다.

2) 엑셀 파일: read_excel / to_excel

pandas에서 엑셀 파일을 불러오고 싶을 때는 read_excel 함수를 사용합니다.

python
df = pd.read_excel('data.xlsx') # 읽어올 파일 경로 + 파일명 + 확장자 입력

반면, pandas에서 만든 데이터를 엑셀 파일로 저장하고 싶다면 아래와 같이 to_excel 함수를 사용하면 됩니다.

python
pd.to_excel('../data/data.xlsx') # 저장할 파일 경로 + 파일명 + 확장자 입력

만일 엑셀 파일 안에 있는 여러 개의 시트 중에서 하나의 시트를 불러오고 싶다면 sheet_name 파라미터에 시트명 또는 시트가 나열된 순서에 해당하는 번호를 입력하면 됩니다. 이때 번호는 0부터 시작합니다.

python
df = pd.read_excel('data.xlsx', sheet_name='SheetName')
# 또는
df = pd.read_excel('data.xlsx', sheet_name=1) # 두 번째 시트 불러오기
df = pd.read_excel('data.xlsx', sheet_name=[0, 2, 'SheetName']) # 첫 번째, 세 번째, 시트명이 SheetName인 시트 불러오기

엑셀 파일을 로딩할 때는 위에서 살펴본 CSV 파일의 옵션 중에서 encoding을 제외한 모든 옵션을 사용할 수 있습니다. 특히, 엑셀 파일을 로딩할 때는 불러오고 싶은 특정 구간의 열을 usecols 옵션을 이용해 슬라이싱으로 지정할 수 있습니다.

특정 구간의 열 지정하기: usecols

엑셀 파일을 불러올 때는 usecols 옵션에 슬라이싱을 사용하면 특정 구간의 데이터만 불러올 수 있습니다. usecols의 슬라이싱 기능은 CSV 파일에서는 작동하지 않습니다. 코드는 다음과 같습니다.

python
df = pd.read_excel('data.xlsx', usecols='B:D') # B 컬럼부터 D 컬럼까지 가져오기

마지막으로 *.txt 파일을 DataFrame 객체로 불러오는 방법을 알아보겠습니다.

3) *.txt 파일: read_csv(sep=' ' or '\t')

파일 확장자가 .txt인 파일을 불러올 때는 CSV 파일을 로딩할 때와 마찬가지로 read_csv 함수를 사용하고, 여기에 sep 옵션으로 구분자를 지정하면 됩니다. .txt 파일은 구분자가 없기 때문에 " " 또는 "\t" 등의 구분자를 넣어주어야 합니다. 예제 코드는 다음과 같습니다.

python
df = pd.read_csv('data.txt', sep='\t') # 구분자 tab 사용

sep 대신 delimiter를 사용해도 됩니다. 지금까지 다양한 종류의 텍스트 파일을 DataFrame 객체로 읽어오고, DataFrame을 저장하는 법을 살펴보았습니다. 다음 단계는 색인을 관리하는 작업입니다. 데이터를 선택하고 분석하기 전에 색인을 관리하면 자료를 더 정확하고 효율적으로 분석할 수 있습니다.

색인 관리하기(Managing index)

색인 객체(index objects)란 표(table) 형식으로 이루어진 자료의 각 행과 열에 대해 메타데이터를 저장하는 객체입니다. DataFrame을 만들 때 살펴본 indexcolumns이 바로 대표적인 색인 객체입니다.

색인 객체는 몇 가지 특징을 지닙니다. 첫째, 인덱스 객체는 배열과 유사하게 고정 크기로 동작합니다. 고정 크기로 동작한다는 의미는 각 값에 할당된 메모리의 크기가 변하지 않고 일정하게 유지된다는 뜻입니다. 둘째, 일단 색인으로 지정한 후에는 색인의 내용을 변경할 수 없습니다. 색인을 변경하고 싶다면 지정한 색인을 해제해야 합니다. 메모리의 크기와 내용이 일정하게 유지되는 점은 색인이 자료구조 사이에서 안전하게 공유되도록 합니다. 따라서, 색인을 잘 다루면 데이터를 분석하는 생산성이 높아집니다.

pandas의 색인은 단층 색인과 다중 색인으로 나뉩니다. 단층 색인은 계층이 1차원인 색인입니다. 다중 색인은 단계(level)가 여러 개 있는 색인을 의미합니다. 다중 색인은 계층적 색인, 멀티인덱스(MultiIndex)라고도 부릅니다. 그럼 색인을 관리하는 도구를 하나씩 살펴보겠습니다.

1) 생성하기: Index

기본 색인

색인은 pandas.Index 클래스로 만들 수 있습니다. 지금까지는 pandas.DataFrameindex 매개변수에 행색인으로 사용할 리스트를 넘겨주었다면, 이번에는 색인 객체를 직접 만들어서 index 매개변수에 넘겨주는 것입니다. 다음 코드는 pandas.Index 클래스로 행색인을 만드는 예시 코드입니다.

python
labels = pd.Index(['철수네', '영희네']) # Index(['철수네', '영희네'], dtype='object')
df = pd.DataFrame(np.arange(8).reshape((2, 4)),
index=labels,
columns=['전체', '밭1', '밭2', '밭3'])
df

계층적 색인

계층적 색인을 만들고 싶다면 pandas.MultiIndex.from_arrays를 이용하면 됩니다.

python
index_arrays = [['A', 'A', 'B', 'B'], [1, 2, 1, 2]]
columns = ['X', 'Y']
data = [[10, 20], [30, 40], [50, 60], [70, 80]]
index = pd.MultiIndex.from_arrays(index_arrays, names=('Letter', 'Number'))
df = pd.DataFrame(data, index=index, columns=columns)
df

2) 확인하기: index, columns

색인명을 확인하려면 DataFrame.indexDataFrame.columns 속성을 이용하면 됩니다. 먼저 행색인을 확인하는 법부터 알아보겠습니다.

행색인: index

행 색인을 알고 싶다면 DataFrame.index 속성을 사용하면 됩니다. 기본 코드는 아래와 같습니다.

python
df.index
# 결과
Index(['철수네', '영희네'], dtype='object')

만약 행 색인에 특정 색인이 있는지 확인하려면 다음 코드를 사용하면 됩니다. 이 코드는 특정 색인의 유무를 불리언 값으로 반환해줍니다.

python
'포켓몬명' in df.index # False 반환
'영희네' in df.index # True 반환

열 색인도 확인해보겠습니다.

열 색인: columns

열 색인을 확인하고 싶다면 DataFrame.columns 속성을 이용하면 됩니다. 기본 코드는 다음과 같습니다.

python
df.columns
# 결과
Index(['전체', '밭1', '밭2', '밭3'], dtype='object')

특정 열 이름이 열 색인에 있는지 확인하려면 다음 코드를 사용하시면 됩니다.

python
'과' in df.columns # False 반환
'밭1' in df.columns # True 반환

파이썬의 집합과는 달리 pandas의 인덱스는 중복되는 값을 허용합니다. 중복되는 색인값을 사용하면 해당 값을 가진 모든 항목이 선택됩니다.

python
labels_duplicated = pd.Index(['감자', '감자', '고구마', '미나리'])
labels_duplicated
# 결과
Index(['감자', '감자', '고구마', '미나리'], dtype='object')

만약 중복되는 색인이 있는지 확인하고 싶다면 DataFrame.is_unique 속성을 사용하면 됩니다. is_unique 속성은 행 색인의 값이 유일한지 아닌지를 알려줍니다.

python
df.index.is_unique # 행 색인 중복 확인
df.columns.is_unique # 열 색인 중복 확인
# 결과
True # 동일한 이름의 행 색인 없음
False # 동일한 이름의 열 색인 있음

3) 지정하기: set_index

특정 열을 행 색인으로 설정하려면 DataFrame.set_index 함수를 사용하면 됩니다.

python
df.set_index('전체') # '전체'라는 이름을 지닌 열을 행 색인으로 지정하기

set_index 함수를 사용해서 얻은 DataFrame은 내부 데이터에 대한 뷰(view) 입니다. 뷰라는 의미는 복사본이 아니라는 뜻입니다. 따라서, 기존의 DataFrame에는 변화가 없습니다. 색인을 지정한 것이 반영되지 않는 것입니다. 만약 DataFrame에 색인으로 지정한 열을 반영하고 싶다면, 기존 DataFrame에 덮어 쓰거나 새로운 DataFrame을 만들거나 inplace 옵션으로 True 값을 전달하면 됩니다.

python
df_new = df.set_index('전체') # 새로운 DataFrame 만들기
# 또는
df = df.set_index('전체') # 기존 DataFrame에 덮어쓰기
# 또는
df.set_index('전체', inplace=True) # 기존 DataFrame에 색인 지정 바로 반영하기

만약 계층적 행 색인을 지정하고 싶다면 set_index에 계층적 색인으로 지정하고 싶은 리스트를 인자로 전달하면 됩니다.

python
df5.set_index(['밭1', '밭2'])

계층적 색인으로 만든 열을 기존처럼 열로도 남겨두려면 다음과 같이 drop=False 옵션을 추가하면 됩니다.

python
df5.set_index(['밭1', '밭2', drop=False]) # 계층적 색인 지정 & 기존처럼 열로도 남기기

4) 정렬하기: sort_index

색인을 정렬하려면 DataFrame.sort_index 함수를 사용하면 됩니다. sort_index 함수는 기본적으로 데이터를 오름차순으로 정렬합니다.

행 색인

python
df.sort_index()

만약 행 색인을 내림차순으로 정렬하고 싶다면 ascending 옵션에 False 값을 주면 됩니다.

python
df.sort_index(ascending=False)

열 색인도 정렬해보겠습니다.

열 색인

열 색인을 정렬하고 싶다면 sort_index 함수에 옵션으로 axis=1 을 주면 됩니다. 여기서 1은 열을 의미합니다. 행 색인과 마찬가지로 열 색인도 기본적으로 오름차순으로 정렬됩니다. 코드는 다음과 같습니다.

python
df.sort_index(axis=1)

열 색인을 내림차순으로 정렬하고 싶다면 행 색인을 내림차순으로 정렬할 때와 마찬가지로 ascending 옵션을 False 값으로 주면 됩니다.

python
df.sort_index(axis=1, ascending=False)

만약 계층적 색인이 있는 경우에 sort_index를 사용하려면 level 옵션을 사용할 수 있습니다. level 옵션은 어느 계층을 기준으로 정렬할 것인지를 지정할 수 있습니다. 예제 코드는 아래와 같습니다.

python
df.sort_index(level=1) # 차상위 계층 정렬

5) 통합 색인명 부여하기: index.name, columns.name

통합 색인명을 지정하고 싶다면 index.namecolumns.name 속성을 이용하면 됩니다. index.name 통합 행 색인명을 지정하고 columns.name은 통합 열 색인명을 지정합니다.

행 색인명 지정: index.name

행 색인명을 지정하려면 index.name 속성을 사용하면 됩니다. 다음 코드는 행 색인명을 '구역'으로 지정합니다.

python
df.index.name = '구역'
# 결과
Index(['철수네', '영희네'], dtype='object', name='구역') # 행 Index 객체에 name 추가됨

index.name을 사용하면 통합 행 색인명이 DataFrame에 바로 반영됩니다.

열 색인명 지정: columns.name

통합 열 색인명을 지정하려면 columns.name 속성을 사용하면 됩니다. 기본 코드는 다음과 같습니다.

python
df.columns.name = '밭'
# 결과
Index(['전체', '밭1', '밭2', '밭3'], dtype='object', name='밭') # 열 Index 객체에 name 추가됨

지정한 열 색인명은 DataFrame에 바로 반영됩니다.

6) 색인명 변경하기: index.names, columns.names

index.names

행 색인명을 변경하고 싶은 경우에는 DataFrame.index.names 속성을 사용하면 됩니다.

python
df.index.names = ['소유주'] # 기존 통합 행색인명이 '소유주'로 변경됨

계층적 색인명을 변경하고 싶을 경우에는 변경하고 싶은 행색인명이 담긴 리스트를 해당 속성에 전달하면 됩니다. 예를 들어 계층적 색인이 '포켓몬명'과 '도감번호'인 DataFrame에서 색인명을 변경하고 싶다면 다음 코드를 사용할 수 있습니다.

python
df.index.names = ['소유주', '번호']

columns.names

열 색인명을 변경하고 싶을 때는 DataFrame.columns.names 속성을 사용하면 됩니다.

python
df.columns.names = ['식별코드'] # 열 색인이 1개일 때 통합 열 색인명을 '식별코드'로 변경

만약 계층적 색인일 경우에는 아래와 같이 리스트를 사용하면 됩니다.

python
df.columns.names = ['ID', '번호']

7) 계층 변경하기: swaplevel

DataFrame.swaplevel 함수는 다중 계층에서 계층의 순서를 바꾸고 정렬합니다. 만약 key1key2의 계층을 서로 바꾸고 싶다면 다음 코드를 사용하면 됩니다.

python
df.swaplevel('key1', 'key2') # 'key1'과 'key2'의 계층 변경, swaplevel(0, 1)과 동일

만약 계층 순서를 서로 바꾼 뒤 최상위 계층을 기준으로 데이터를 정렬하고 싶다면 다음 코드를 사용할 수 있습니다.

python
df.swaplevel(0, 1).sort_index(level=0) # 계층 순서 바꾼 뒤 최상위 계층 정렬

8) 재색인하기: reindex, rename, index.map

재색인(reindexing)은 새로운 색인에 맞도록 객체를 새로 생성하는 작업을 의미합니다. 재색인을 하는 방법에는 reindex 속성, rename 함수, index.map을 이용하는 방법이 있습니다.

reindex

reindex를 호출하면 데이터를 새로운 색인에 맞게 재배열합니다. 존재하지 않는 색인값이 있다면 NaN으로 처리됩니다. 예제를 통해 알아보겠습니다.

행 재색인

먼저 행을 재색인해보겠습니다. 예제 코드는 다음과 같습니다.

python
df.reindex(['짱구네', '영희네'])) # 행 재색인
# 결과
전체 밭123
짱구네 NaN NaN NaN NaN
영희네 4.0 5.0 6.0 7.0

시계열 같은 순차적인 데이터를 재색인할 때는 값을 보간하거나 채워 넣어야 할 경우가 있습니다. 이때는 method 옵션을 이용해 누락된 값을 채워 넣을 수 있습니다.

python
object = pd.Series(['개', '고양이', '토끼'], index=[0, 2, 4])
object
# 결과
0
2 고양이
4 토끼
dtype: object
object.reindex(range(6), method='ffill') # 누락된 값을 직전의 값으로 채워 넣기
# 결과
0
1
2 고양이
3 고양이
4 토끼
5 토끼
dtype: object
열 재색인

다음은 열을 재색인하는 코드입니다.

python
columns = ['밭1', '논1', '밭2', '밭4']
df.reindex(columns=columns) # 열 재색인
# 결과
1124
0 1 NaN 2 NaN
1 5 NaN 6 NaN

'밭1'과 '밭2' 색인은 기존에 있었기 때문에 값을 불러왔습니다. 새로 추가된 색인 '논1'과 '밭4'는 불러올 값이 없어 NaN으로 표시되었습니다.

rename

DataFrame의 행 이름 또는 열 이름을 바꾸고 싶다면 rename 메서드를 사용하면 됩니다.

python
df.rename(index={'영희네': 'Eun네'}, # 행 색인명 '영희네'를 'Eun네'로 변경
columns={'밭1': '논1'}) # 열 색인명 '밭1'을 '논1'로 변경
# 결과
전체 논123
철수네 0 1 2 3
Eun네 4 5 6 7

아래 예시는 모든 행 색인명과 열 색인명을 한 번에 바꾸는 예제입니다.

python
df.rename(index=str.title, # 영문으로 된 모든 행 이름의 첫 글자를 대문자로, 나머지는 소문자로 변경
columns=str.upper) # 영문으로 된 모든 열 이름을 대문자로 변경

rename 메서드는 원래 객체를 변경하지 않고 새로운 객체를 생성해서 행 또는 열의 이름을 변경해 줍니다. 원본 DataFrame은 보존하고 복사한 DataFrame의 색인명을 바꾸고 싶다면 copy 메서드를 이용하면 됩니다.

python
df_copy = df.copy()
df_copy = df.rename(columns={'밭1':'논1'}) # 기존 변수명인 '밭1'을 새 변수명인 '논1'로 변경

만일, 복사본을 생성하지 않고 원본 DataFrame에 변경 사항을 바로 반영하고 싶다면 inplace=True 옵션을 주면 됩니다.

index.map

index.map 함수를 사용하면 행 색인으로 지정한 값 전부를 변경할 수 있습니다. 이 함수를 사용하면 행 색인의 변경된 값이 DataFrame에 바로 반영됩니다.

python
transform = lambda x: x[:3].upper()
df.index = df.index.map(transform)
# 결과
Index(['EUN', 'HAN'], dtype='object')

9) 초기화하기: reset_index

reset_index 함수는 set_index와 반대되는 함수입니다. reset_index 함수는 색인을 초기화합니다. 이 함수는 계층적 색인을 지정했을 때 다시 열 단위의 DataFrame으로 만들어 주는 역할도 합니다.

python
df.reset_index()
df.reset_index(drop=True) # 사용했던 색인을 삭제
df.reset_index(drop=True, inplace=True) # 사용했던 색인을 삭제하고 DataFrame에 반영

지금까지 Python pandas 사용법으로 데이터 프레임을 생성하는 법, 데이터를 로딩하고 저장하는 법 그리고 색인을 관리하는 법을 알아보았습니다. 이어지는 시리즈는 Python pandas 데이터 확인, 정렬, 선택하는 법입니다. 여기에서는 DataFrame의 데이터를 확인하고, 정렬 및 선택하는 법을 알아보겠습니다. 모두 수고 많으셨습니다.

참고 문헌

...

©2023 Snug Archive. All rights reserved.

Contact me at snugarchive@gmail.com.