/ PROGRAMMING, PYTHON

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을 의미한다.

가장 기본적인 사용법은 위와 같이 rowcolumn 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

시리즈의 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)
DataFrame.replace(to_replace=None, value=_NoDefault.no_default, *, inplace=False, limit=None, regex=False, method=_NoDefault.no_default)

to_replace로 전달된 값을 value로 치환한다.

to_replacedict를 전달하면, 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 DataFrameseason column의 모든 1'spring'으로 치환한다.

to_replacenested 딕셔너리를 전달하고 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() 메소드는 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의 SeriesDataFramenumpy의 함수들을 비롯한 수학적인 operation들을 지원한다.

np.mean(df)
max(df)