Python - Pandas 모듈
데이터 분석 및 핸들링에 사용되는 Pandas 모듈의 기본적인 개념 및 기능, 사용법 등을 정리했다.
자료구조
DataFrame
행과 열로 구성된 2차원 자료구조이다. 엑셀의 스프레드시트와 유사하다.
같은 Index
를 공유하는 Series
들이 모여있는 것으로 생각할 수 있다.
새로운 DataFrame
은 다음과 같이 생성할 수 있다.
import pandas as pd
data = {
'column_name_1': [1, 2, 3, 4, 5],
'column_name_2': [6, 7, 8, 9, 10],
...
}
df = pd.DataFrame(data, columns = ['column_name_1', 'column_name_2', ...])
Series
1차원 자료구조이며 벡터 또는 하나의 열로 생각하면 편하다.
Index
연속된 row label들에 해당한다.
반드시 숫자일 필요는 없으며, 이름을 가질 수도 있다.
그리고 각 index는 unique하지 않을 수도 있다.
단 column 명은 unique해야 한다.
[]
연산자로 인덱싱하기
DataFrame
객체에 대해 다음과 같이 인덱싱이 가능하다.
# column 인덱싱
df['column_name'] # column명을 전달하면 해당 column을 Series로 반환
df[['column_name_1', 'column_name_2']] # column명의 리스트를 전달하면 해당 column들을 모아서 DataFrame으로 반환
# row 인덱싱
df[0:3] #row index를 전달하면 해당 row들을 모아서 DataFrame으로 반환
row 인덱싱 시 주의할 점은 반드시 slicing을 해야 한다는 것이다. df[0]
과 같이 인덱싱 하려고 하면 0
이 column명으로 인식되어 정수 0
을 이름으로 가진 column이 선택된다.
Boolean Array로 indexing하기
[]
연산자가 지원하는 또 다른 타입은 Bool
타입 리스트이다.
이때 Bool
리스트의 각 요소는 하나의 row에 대응된다.
직접 리스트를 만들어서 전달할 수도 있지만, 이 Bool
리스트는 Series
에 대한 논리 연산자를 사용해서도 생성이 가능하다.
df[df['column_name'] == 'value']
위 예시와 같이 작성하면 column_name
column의 값이 'value'
인 row들만을 선택한다.
&
연산자로 여러 개의 Bool Series
들을 결합할 수도 있다.
df[(df['column_name_1'] == 'value_1') & (df['column_name_2'] == 'value_2')]
isin
메소드 활용
isin
함수는 Series
객체의 메소드로, Series
객체의 값이 list
에 포함되어 있는지 여부를 Bool
리스트로 반환한다.
인덱싱 시에는 여러 개의 값을 선택하고 싶을 때 유용하다.
df[df['column_name'].isin(['value_1', 'value_2'])]
query
메소드 활용
query
함수는 DataFrame
객체의 메소드로, DataFrame
객체의 특정 column에 대한 조건을 문자열로 전달하면 해당 조건에 맞는 row들만을 선택한다.
df.query('column_name == "value"')
.loc
과 .iloc
로 인덱싱하기
[]
대신 인덱싱 시 사용할 수 있는 메소드이다.
.loc
loc
은 []
연산자를 사용할 때와 같이 label
을 기준으로 인덱싱하거나, boolean array로 인덱싱할 수 있다.
df.loc[[0, 1, 2], ['column_name_1', 'column_name_2']]
loc[]
내에서 첫 번째 요소는 row
를, 두 번째 요소는 column
을 의미한다.
가장 기본적인 사용법은 위와 같이 row
와 column
label의 리스트를 전달하는 것이다.
슬라이싱을 통해 인덱싱할 수도 있다.
df.loc[0:2, 'column_name_1':'column_name_2']
이때 주의할 점은 loc
의 슬라이싱은 inclusive하다는 것이다.
즉, :
뒤에 붙는 label도 포함된다. 반대로 뒤에서 다룰 iloc
은 exclusive하다는 차이가 있으니 주의하자.
column argument로 하나의 label만 전달하면 DataFrame
이 아닌 Series
가 리턴된다.
row argument로 하나의 label만 전달해도 Series
가 리턴된다. 선택된 column argument들을 인덱스로 갖는다.
Boolean array 역시 []
연산자를 사용할 때처럼 사용 가능하다.
df.loc[df['column_name'] == 'value']
.loc
으로 정렬하기
.loc[idx]
형태로 사용하면 idx
와 같은 순서로 정렬된 상태의 DataFrame
을 반환한다.
인덱스가 DataFrame
과 완전히 일치할 때만 동작한다.
name_lengths = babynames["Name"].str.len()
name_lengths.sort_values(inplace=True)
idx = name_lengths.index
babynames.loc[idx]
위 예시에서는 babynames
라는 DataFrame
에서 Name
column에 있는 값들의 길이를 기준으로 정렬한 인덱스를 얻어낸 뒤, 그 순서대로 DataFrame
을 정렬한다.
.iloc
이름의 i
에서 알 수 있듯이, 오직 정수만 사용하여 C의 배열처럼 numerical한 위치로 인덱싱을 한다. label은 사용하지 않는다.
df.iloc[0:2, 0:2]
일반적인 경우 loc
을 사용하는 것이 권장된다.
Column 추가 및 수정, 삭제
우선 추가하고 싶은 column으로 이루어진 Series
객체를 만든다.
그 이후 DataFrame
객체에 []
연산자를 사용하여 column을 추가한다.
new_column = pd.Series([1, 2, 3, 4, 5])
df['new_column'] = new_column
.drop()
메소드를 사용하여 column을 삭제할 수 있다.
df.drop('new_column', axis=1)
.drop()
메소드는 기본적으로 row를 삭제한다. 따라서 axis=1
을 전달하여 column을 삭제하도록 지정해야 한다.
함수
read_csv()
함수
.csv
파일을 로드하여, DataFrame
객체로 반환한다.
bike = pd.read_csv(workspace_path+'bikeshare.txt')
Series
클래스의 메소드 및 attributes
.value_counts()
메소드
시리즈의 unique한 값 및 개수가 들어있는 Series
객체를 리턴한다.
.unique()
메소드
시리즈의 unique한 값들을 리스트로 리턴한다.
.str
attribute
문자열 값들을 다루는 메소드를 가지고 있다.
예를 들어 .startswith()
같은 메소드를 사용 가능하다.
전체 리스트는 여기에서 확인 가능하다.
df['column_name'].str.<method_name>()
위와 같은 방식으로 사용 가능하다.
.map()
메소드
dict
또는 function
을 인자로 받아, 시리즈의 각 값에 대해 dict
의 key에 해당하는 값으로 대체하거나, function
을 적용한 결과로 대체한 Series
를 리턴한다.
df['double_column'] = df['column_name'].map(lambda x: x*2)
df = df.sort_values(by = 'double_column', ascending = False)
DataFrame
클래스의 메소드 및 attributes
.head()
메소드
데이터 프레임의 앞부분 row들을 출력한다.
bike = pd.read_csv(workspace_path+'bikeshare.txt')
bike.head()
.describe()
메소드
데이터에 대한 요약을 제공한다.
size
attribute
row의 수에 해당한다.
shape
attribute
데이터 프레임의 (<row 수>, <column 수>)
튜플에 해당한다.
index
attribute
인덱스(row labels)에 해당한다.
columns
attribute
컬럼명(column labels) 리스트에 해당한다.
sort_values()
메소드
특정 column을 기준으로 정렬한 결과 DataFrame
또는 Series
를 리턴한다.
기본적으로 오름차순으로 정렬되며, ascending=False
옵션을 통해 내림차순으로 정렬할 수 있다.
df.sort_values(by='season', ascending=False)
replace()
메소드
DataFrame.replace(to_replace=None, value=_NoDefault.no_default, *, inplace=False, limit=None, regex=False, method=_NoDefault.no_default)
to_replace
로 전달된 값을 value
로 치환한다.
to_replace
에 dict
를 전달하면, value
parameter의 생략 여부에 따라 행위가 달라진다.
우선 value
parameter를 생략하면, dict
의 key를 DataFrame
내의 값으로 취급하고, 해당 값을 dict
의 value로 치환한다.
bike.replace({1: 'spring', 2: 'summer', 3: 'fall', 4: 'winter'})
위 예시는 bike
DataFrame
내 모든 값들을 1
을 'spring'
으로, 2
를 'summer'
로, 3
을 'fall'
로, 4
를 'winter'
로 치환한다.
value
parameter를 생략하지 않고 어떠한 값을 전달하면, to_replace
에 전달된 dict
의 key를 DataFrame
내의 column으로 취급하고, 해당 dict
의 value를 value
parameter로 치환한다.
bike.replace({'season' : 1}, 'spring')
위 예시는 bike
DataFrame
내 season
column의 모든 1
을 'spring'
으로 치환한다.
to_replace
에 nested 딕셔너리를 전달하고 value
parameter를 생략할 수도 있다.
column name에 해당하는 가장 상위 레벨 딕셔너리의 key만을 제외하고 정규 표현식을 사용할 수도 있다.
bike.replace({'season': {1: 'spring', 2: 'summer', 3: 'fall', 4: 'winter'}})
위 예제에서는 season
column의 1, 2, 3, 4를 각각 'spring'
, 'summer'
, 'fall'
, 'winter'
로 치환한다.
.groupby().agg()
메소드
서로 다른 두 개의 메소드지만 같이 쓰이는 경우가 잦으므로 함께 소개한다.
.groupby()
메소드는 DataFrame
을 parameter에 전달된 column을 기준으로 그룹화한다.
리턴되는 것은 DataFrameGroupBy
객체로, DataFrame
객체가 아니다!
이 객체에는 .agg()
뿐만 아니라 .size()
, .filter()
메소드도 이용 가능하다.
.size()
메소드는 각 그룹의 row 수를 리턴한다.
.filter()
메소드는 각 그룹에 대해 function
(input: DataFrame
, output: Bool
)을 적용한 결과가 True
인 그룹만 남기고 제거한 DataFrame
을 리턴한다.
이때 이 function
은 그룹화된 각 subframe에 대해 적용된다.
.agg()
메소드는 groupby
메소드로 그룹화된 DataFrame
(사실은 DataFrameGroupBy
객체)에 대해 agg
parameter에 스트링 형태로 전달된 함수(aggregation function)를 적용한다.
aggregation function의 parameter는 Series
이고 리턴값은 scalar
여야 한다.
DataFrame
의 모든 column에 대해 각각 aggregation function이 적용된 결과가 리턴되므로 의도치 않은 column에 대해 aggregation function이 적용될 수 있으니 주의해야 한다.
각 column에 대해 서로 다른 aggregation function을 적용하고 싶을 경우 다음과 같이 딕셔너리 형태로 전달하면 된다.
또 하나의 column에 여러 개의 aggregation function을 적용하고 싶을 경우 aggregation function 함수명의 리스트를 전달하면 된다.
df.groupby('A').agg({'B': ['min', 'max'], 'C': 'sum'})
.agg(max)
나 .agg(sum)
은 .max()
나 .sum()
으로 줄여서 쓸 수도 있다.
.sample()
메소드
DataFrame
객체 내에서 인자로 전달된 수만큼의 row를 무작위로 선택한다.
기본적으로는 replace=False
로 설정되어 있어서, 중복된 row를 선택하지 않는다.
df.sample(n=5, replace=False)
Numpy Operations
Pandas의 Series
및 DataFrame
은 numpy
의 함수들을 비롯한 수학적인 operation들을 지원한다.
np.mean(df)
max(df)