판다스(Pandas)란?

  • 파이썬에서 데이터 처리를 위해 존재하는 가장 인기 있는 라이브러리
  • 행(row)과 열(column)로 구성된 2차원 데이터를 효율적으로 가공/처리하는 데 활용
  • 파이썬의 리스트, 컬렉션, 넘파이 등의 내부 데이터뿐만 아니라 csv 등의 파일을 쉽게 DataFrame으로 변경해 데이터의 가공/분석을 편리하게 수행할 서 있게 해줌
  • 데이터프레임(DataFrame)
    • 여러 개의 행과 열로 이뤄진 2차원 데이터
    • Index: RDBMS의 PK처럼 개별 데이터를 고유하게 식별하는 key값
    • Series: 칼럼이 하나인 데이터 구조체
      • DataFrame은 여러 개의 Series로 이뤄졌다고 할 수 있음

1. 판다스 시작 - 파일을 DataFrame으로 로딩, 기본 API

● 판다스 모듈 import

import pandas as pd

● 파일을 열기 위한 API

  • read_csv(filepath, sep = ',', ...)
    • csv(칼럼을 ‘,’로 구분한 파일 포맷) 파일 포맷 변환
      • 파일을 로딩해 DataFrame 객체로 반환
    • csv 뿐만 아니라 어떤 필드 구분 문자 기반의 파일 포맷도 변환 가능
      • sep 인자를 통해 필드 구분 문자(delimeter) 지정
    • 파이썬 실행 파일이 있는 디렉터리와 동일한 디렉터리에 파일이 있는 경우 filepath에 파일명만 입력해도 ok
    • 별다른 파라미터 지정이 없으면 파일의 맨 처음 row를 칼럼명으로 활용
  • read_table(): 칼럼을 탭(‘\t’)으로 구분한 파일 포맷) 파일 포맷 변환
  • read_fwf(): 고정 길이 기반의 칼럼 포맷을 DataFrame으로 로딩

● 데이터 표시/확인

  • pd.DataFrame.head(n): 맨 앞에 있는 n개의 row 반환(default = 5)
  • pd.DataFrame.shape: DataFrame의 행과 열을 튜플 형태로 반환
  • pd.DataFrame.info(): 칼럼의 타입, Null 데이터 개수, 데이터 분포도 등의 메타 데이터 확인
    • RangeIndex: DataFrame의 index 범위 => 전체 행의 개수 파악 가능
    • dtypes: 데이터 칼럼들의 타입을 요약한 것
  • pd.DataFrame.describe():
    • 칼럼별 숫자형 데이터값의 n-percentile 분포도, 평균값, 최댓값, 최솟값 등을 나타냄
    • 오직 숫자형(int, float 등) 칼럼의 분포도만 조사함
    • 개략적인 수준의 분포도를 확인할 수 있음
    • 특정 컬럼이 숫자형 카테고리 칼럼인지를 판단하는 데 도움을 줌
    • count: Not Null인 데이터 건수

Series 객체

  • Index와 단 하나의 컬럼으로 구성된 데이터 세트
  • DataFrame의 [ ] 연산자 내부에 칼럼명 입력 시 Series 형태로 특정 칼럼 데이터 세트가 반환됨
<class 'pandas.core.series.Series'>
  • pd.Series.value_counts():
    • Series 객체 반환
    • 지정된 칼럼의 데이터값 건수를 반환
    • 많은 건수 순서로 정렬되어 값을 반환

● 판다스의 index 객체

  • 모든 DataFrame 내의 데이터는 생성되는 순간 고유의 Index 값을 가지게 됨
  • 단순히 순차 값과 같은 의미 없는 식별자만 할당하는 것이 아닌 고유성이 보장된다면 의미 있는 데이터값고 할당 가능
  • 문자열도 인덱스로 지정 가능

※ 모든 인덱스는 고유성이 보장되어야 함

2. DataFrame과 리스트, 딕셔너리, 넘파이 ndarray 상호 변환

  • DataFrame은 다양한 데이터로부터 생성될 수 있고, 다양한 데이터로 변환할 수 있음

● 넘파이 ndarray, 리스트, 딕셔너리를 DataFrame으로

  • DataFrame은 리스트/ 넘파이 ndarray와 다르게 칼럼명을 가지고 있음
    • DataFrame으로 변환 시 칼럼명을 지정해 줌(지정 x -> 자동으로 칼럼명 할당)
  • pd.DataFrame(data, columns = ): pandas DataFrame을 생성하는 함수
  • DataFrame은 기본적으로 행과 열을 가지는 2차원 데이터
    • 2차원 이하의 데이터들만 DataFrame으로 변환될 수 있음
  • 1차원 형태의 데이터를 기반으로 DataFrame 생성 시 칼럼명은 1개가 필요
    • 2차원인 경우 열의 개수만큼
  • 딕셔너리의 경우 key는 칼럼명으로, 값(value)는 키에 해당하는 칼럼 데이터로 변환됨

● DataFrame을 넘파이 ndarray, 리스트, 딕셔너리로 변환

  • pd.DataFrame.values: pd.DataFrame -> np.ndarray
  • pd.DataFrame.values.toist()`: pd.DataFrame -> list
  • pd.DataFrame.to_dict()
    • pd.DataFrame -> 딕셔너리
    • 인자로 ‘list’ 입력 시 딕셔너리의 값이 리스트형으로 반환됨

3. DataFrame의 컬럼 데이터 셋 생성과 수정

  • [ ] 연산자 이용
  • 새로운 칼럼 생성 시 DataFrame[] 내에 새로운 칼럼명을 입력하고 값을 할당해주기만 하면 됨
  • 기존 칼럼 Series의 데이터를 이용해 새로운 칼럼 Series를 생성할 수 있음
  • 기존 칼럼 값을 변경하려면 업데이트를 원하는 칼럼 Series를 DataFrame[] 내에 칼럼명으로 입력한 뒤 값을 할당해 주면 됨

4. DataFrame 데이터 삭제

  • pd.DataFrame.drop(): DataFrame에서 데이터 삭제
DataFrame.drop(labels= None, axis = 0, index = None, columns = None, level = None, inplace = False, erros = 'raise')
  • labels:
    • drop을 희망하는 칼럼명을 지정
    • 여러 개의 칼럼 삭제 희망 시 리스트 형태로 삭제하고자 하는 칼럼명을 입력하면 됨
  • axis: drop 수행 시 축을 지정(axis=0: 행, axis=1: 열)

  • inplace = True
    • 자신의 DataFrame의 데이터를 삭제
    • 반환값: None -> 다시 자신의 DataFrame 객체에 할당하면 안 됨

5. Index 객체

  • DataFrame, Series의 레코드를 고유하게 식별하는 객체
  • index 속성을 통해 Index 객체만 추출 가능
  • 반한된 Index 객체의 실제 값은 넘파이 1차원 ndarray로 확인 가능
    • Index.values로 확인
  • 식별성 데이터를 1차원 array로 가지고 있음
  • ndarray와 유사하게 단일 값 반환 및 슬라이싱 가능
  • 한 번 만들어진 DataFrame 및 Series의 Index 객체는 함부로 변경할 수 없음
  • Series 객체에 연산 함수 적용 시 Index는 연산에서 제외됨
    • Index는 오직 식별용으로만 사용됨
  • reset_index()
    • DataFrame 또는 Series에 새롭게 인덱스를 연속 숫자 형으로 할당
      • 기존 인덱스는 index라는 새로운 칼럼으로 추가됨
      • Series에 적용 시 DataFrame이 반환됨
        • 기존 index가 칼럼으로 추가되어 칼럼 수가 2개가 되므로
      • drop = True: 기존 인덱스가 새로운 칼럼으로 추가되지 않고 삭제(drop)됨
        • Series의 경우 그대로 Series로 유지됨

6.데이터 셀렉션 및 필터링

● DataFrame의 [ ] 연산자

  • 칼럼 명 문자(칼럼 명의 리스트 객체) or 인덱스로 변환 가능한 표현식이 들어갈 수 있음
    • 인덱스(숫자) 사용 시 에러 발생(KeyError)
    • 슬라이싱의 경우 판다스의 인덱스 형태로 변환 가능 -> 에러x
      • but 사용을 권장하진 않음
    • 불린 인덱싱 표현도 가능함

● 명칭 기반 인덱싱과 위치 기반 인덱싱의 구분

  • 명칭(label) 기반 인덱싱
    • 칼럼의 명칭을 기반으로 위치를 지정하는 방식
    • ‘칼럼 명’과 같이 명칭으로 열 위치를 지정하는 방식
  • 위치(Position) 기반 인덱싱
    • 0을 출발점으로 하는 가로축, 세로축 좌표 기반의 행과 열 위치를 기반으로 데이터 지정
    • 행, 열의 위치 좌표에만 의존
  • 결과적으로 DataFrame의 인덱스 값은 명칭 기반 인덱싱이라고 간주해야 함

● DataFrame의 iloc[] 연산자

  • 위치 기반 인덱싱
    • 행과 열 값으로 integer 또는 integer형의 slicing, 팬시 리스트 값을 입력해 줘야 함
  • 슬라이싱과 팬시 인덱싱 제공
    • but 명확한 위치 기반 인덱싱이 사용되어야 함 -> 불린 인덱싱은 제공 x

● DataFrame의 loc[] 연산자

  • 명칭 기반 인덱싱
    • 행 위치에는 DataFrame의 index값 입력
    • 열 위치에는 칼럼명 입력
  • ⭐ loc에 슬라이싱을 적용하는 경우 종료 값 또한 포함
    • 명칭 기반 인덱싱의 특성

● 불린 인덱싱

  • iloc[]에서는 지원 x
  • [] 내에 불린 인덱싱 적용 시 반환되는 객체는 DataFrame
    • 원하는 칼럼 명만 별도로 추출할 수 있음
  • ex>
    titanic_df[titanic_df['Age'] > 60][['Name','Age']].head(3)
    
  • loc[]를 이용하는 경우 칼럼 위치에 놓여야 함
    titanic_df.loc[ titanic_df['Age'] > 60, ['Name','Age'] ].head(3)
    
  • 여러 개의 복합 조건도 결합하여 적용 가능
    • and 조건: &
    • or 조건:
    • Not 조건: ~
    • 개별 조건을 변수에 할당하고 이들 변수를 결합하여 불린 인덱싱을 수행할 수도 있음
      cond1 = titanic_df['Age'] > 60
      cond2 = titanic_df['Pclass']==1
      cond3 = titanic_df['Sex']=='female'
      titanic_df[ cond1 & cond2 & cond3]
      

7. 정렬, Aggregation 함수, GroupBy 적용

● DataFrame, Series의 정렬 - sort_values()

  • sort_values(by, ascending, inplace)
    • by:
      • 정렬을 수행할 기준 컬럼
      • 여러 컬럼을 지정하려는 경우 리스트 형식으로 입력하면 됨
    • ascending = True: 오름차순 정렬(default: ascending = True)
    • inplace = True: 호출한 DataFrame의 정렬 결과를 원본 DataFrame에 덮어씀(default: inplace = False)

●Aggregation 함수 적용

  • min(), max(), sum(), count() 등
  • DataFrame에서 바로 aggregation을 호출할 경우 모든 칼럼에 연산 적용
    • 특정 칼럼에만 적용하려면 칼럼 추출 후 aggregation을 적용해야 함

● groupby() 적용

  • by 파라미터로 지정된 칼럼으로 groupby
  • DataGroupBy라는 또 다른 형태의 DataFrame을 반환
<class 'pandas.core.groupby.generic.DataFrameGroupBy'>
  • DataFrame에 groupby()를 호출한 후 반환된 결과에 aggregation 함수를 호출하면 groupby() 대상 칼럼을 제외한 모든 칼럼에 해당 aggregation 함수를 적용
  • 특정 칼럼만 aggregation 함수를 적용하려면 groupby()로 반환된 DataFrameGroupBy 객체에 해당 칼럼을 필터링한 뒤 aggregation 함수를 적용
    ex>

    titanic_groupby = titanic_df.groupby('Pclass')[['PassengerId', 'Survived']].count()
    titanic_groupby
    
  • 서로 다른 aggregation 함수를 적용할 시 여러 개의 aggregation 함수명을 DataFrameGroupBy 객체의 agg() 내에 인자로 입력해서 사용
  • 여러 개의 칼럼이 서로 다른 aggregation 함수를 groupby에서 호출하려면 agg() 내에 딕셔너리 형태로 칼럼명과 함수를 입력
    ex>

    agg_format={'Age':'max', 'SibSp':'sum', 'Fare':'mean'}
    titanic_df.groupby('Pclass').agg(agg_format)
    

8. 결손 데이터 처리하기

  • 결손 데이터
    • 칼럼에 값이 없는, 즉 NULL인 경우를 의미
    • 넘파이의 NaN으로 표시
    • 기본적인 머신러닝 알고리즘에서 처리되지 x
    • 평균, 총합 등의 함수 연산 시 제외됨
  • pd.DataFrame.isna()를 통해 NaN 여부 확인
  • pd.DataFrame.fillna()를 통해 NaN을 다른 값으로 대체

● isna()로 결손 데이터 여부 확인

  • 모든 칼럼의 값이 NaN인지 아닌지를 True/False 값으로 알려줌
  • isna() 결과에 sum() 함수를 추가해 결손 데이터의 개수를 구할 수 있음
    • True는 내부적으로 숫자 1로, False는 숫자 0으로 변환됨

● fillna( ) 로 Missing 데이터 대체하기

  • 결손 데이터를 다른 값으로 대체
  • pd.DataFrame.fillna('대체값') 형태
  • fillna()를 이용해 반환 값을 다시 받거나 inplace = True 파라미터를 추가해야 실제 데이터 세트에 값이 변경됨

9. apply lambda 식으로 데이터 가공

  • apply 함수에 lambda 식을 결합해 레코드별로 데이터를 가공할 수 있음
  • lambda 식
    • 함수의 선언과 함수 내의 처리를 한 줄의 식으로 쉽게 변환하는 식
    • lambda x: x**2: 왼쪽은 입력 인자, 오른쪽은 입력 인자의 계산식
    • 여러 개의 값을 입력 인자로 사용 시 보통 map() 함수를 결합하여 사용
    • if~else절 사용 시 if 식보다 반환 값을 먼저 기술해야 함

    • 더 세분화된 분류가 필요한 경우 아예 별도의 함수를 만든 후 이를 호출
      ex>
    titanic_df['Age_cat'] = titanic_df['Age'].apply(lambda x : get_category(x)) # 사용자 지정 함수 
    titanic_df[['Age','Age_cat']].head()
    

📚 Reference

  • 파이썬 머신러닝 완벽가이드_권철민 저, 개정2판(p.39 ~ 86)