Pandas 기본 개념
- 데이터 : 일반적으로 2차원 (row * column)
- numpy보다 유연하고 편리한 데이터 핸들링
- numpy의 ndaaray 내의 데이터 타입은 그 연산의 특성상 같은 데이터 타입만 가능함(한 개의 ndarray 객체에 int, float 함께 존재 X)
- pandas의 DataFrame내에는 column마다 다른 data type이 가능
- 핵심 객체 : DataFrame(행,열로 구성된 2차원 데이터를 담은 데이터 구조체)
- Series : 칼럼이 1개뿐인 데이터 구조체
- DataFrame : 칼럼이 여러 개인 데이터 구조체
- index : 개별 데이터를 고유하게 식별하는 Key값, Series와 Dataframe 모두 index를 가짐
- 주로 read_csv(filepath_or buffer, sep=',', ...) 사용 -> csv : comma-separated values. 칼럼을 ','로 구분한 파일 포맷
- filepath에서 주의할 사항
- ipynb파일위치 != data위치 : read_csv(r'file path', sep = '..')
- ipynb파일위치 == data위치 : read_csv('file name', sep = "..")
- filepath에서 주의할 사항
Q. Why do we have to use 'r' before path-name while using pd.read_csv?
A. In python, backslash is used to signify special character. Pathnames on Windows tend to have backslashes in them. But we want them to mean actual backslashes, not special characters.
'r' stands for 'raw' and will cause backslashes in the string to be interpreted as actual backslashes rather than special character.
- list, dictionary로부터 DataFrame 생성 : pd.DataFrame
- from list : col_name list생성, 이중list로 value표현
- from dictionary : key값은 칼럼명, value는 각 칼럼 데이터로 매핑됨
In [36]:
import pandas as pd
In [37]:
# list로부터 DataFrame 생성
# 칼럼명이 될 리스트 생성
col_name = ['A','B','C']
# value에 대한 리스트 생성
value_list = [['v1','v2','v3'],
[1,2,3]]
# DataFrame 생성
df_from_list = pd.DataFrame(data=value_list, columns=col_name)
df_from_list
Out[37]:
In [38]:
# dictionary로부터 DataFrame 생성
# Key는 문자열 칼럼명으로 매핑, Value는 리스트 형 또는 ndarray 칼럼 데이터로 매핑
dictionary = {'A':['v1',1], 'B':['v2',2], 'C':['v3',3]}
df_from_dict = pd.DataFrame(dictionary)
df_from_dict
Out[38]:
DataFrame 행/열 삭제
- DataFrame 데이터 삭제 : df.drop()
- axis = 1 : column 삭제
- df.drop(['col1','col2',...], axis=1)
- axis = 0 : row 삭제
- inplace = True : 원본파괴
- inplace = False (default) : 새로운 객체로 받아야 함
- axis = 1 : column 삭제
index와 reset_index
- DataFrame_name.index or Series_name.index : generator와 같은 상태 (반복문 대상 가능)
- 리스트 형태로 출력 : df.index.values or series.index.values
- reset_index() ★★★
- 새롭게 인덱스를 연속 숫자형으로 할당.
- inplace=True : 원본 파괴
- inplace=False(default) : 원본은 유지, 새로운 객체에 할당해야함.
- drop=True
- parameter 추가하지 않으면 기존의 index는 'index' 칼럼명을 가진채 칼럼으로 새로 추가됨
In [39]:
df_from_dict.drop('A', axis=1, inplace=True)
df_from_dict
Out[39]:
In [40]:
df_from_dict.reset_index(inplace=True, drop=False)
df_from_dict
Out[40]:
DataFrame의 인덱싱
- DataFrame의 [ ]연산자
- DataFrame 바로 뒤의 '[ ]'안에 들어갈 수 있는 것?
- 칼럼명문자(또는 칼럼 명의 리스트 객체)
- titanic_df['Pclass']
- 인덱스로 변환 가능한 표현식(불린 인덱싱)
- titanic_df[0:2]
- titanic_df[titanic_df['Sex']=='Female']
- 칼럼명문자(또는 칼럼 명의 리스트 객체)
- DataFrame 바로 뒤의 '[ ]'안에 들어갈 수 있는 것?
- 명칭기반인덱싱 vs 위치기반인덱싱
- 명칭기반인덱싱 : 칼럼의 명칭을 기반으로 위치를 지정
- loc
- 슬라이싱에서 a:b일 때, b 포함O -> 슬라이싱에서 끝을 포함!
- loc는 불린 인덱싱 지원 O
- 위치기반인덱싱 : 0을 출발점으로 하는 가로, 세로의 좌표기반의 행/열 위치로 데이터 지정
- iloc
- 슬라이싱에서 a:b일 때, b 포함X
- iloc는 불린 인덱싱 지원 X
- 명칭기반인덱싱 : 칼럼의 명칭을 기반으로 위치를 지정
- df.loc[index, column]
In [41]:
df_from_dict.loc[0, 'B']
Out[41]:
In [42]:
df_from_dict.loc[0, ['B','C']]
Out[42]:
타이타닉 데이터로 해보는 Pandas 전처리 실습
In [43]:
import pandas as pd
df = pd.read_csv(r'data/titanic_train.csv')
df.head(3)
Out[43]:
In [44]:
# shape : row, column 크기 파악
df.shape
Out[44]:
- info() / describe() 함수 : 메타 데이터 조회
- info() : 총 데이터 건수, 데이터 타입, Null 건수 파악
- describe() : 숫자형 데이터로 된 컬럼에 대해 작동, n-percentile 분포, 평균, 최대최소값 등 개략적인 데이터 분포도 확인
In [45]:
# info
df.info()
In [46]:
# describe
df.describe()
Out[46]:
불린 인덱싱 / 복합 조건 연결식
- df[df[컬럼]에 대한 조건][[여러 컬럼들]] -> 컬럼설정 시 이중대괄호 주의
- df.loc[불린식, [컬럼들]]
- 복합 조건 연결식
- and 조건 : &
- or 조건 : |
- Not 조건 : ~
In [47]:
df[df['Age']>60][['Fare','Sex','Survived']].head(3) # [[컬럼]] 컬럼 순서도 변환됨 주의!
Out[47]:
In [48]:
# 위의 불린 인덱싱을 loc로 표현
df.loc[df['Age']>60, ['Fare','Sex','Survived']].head(3)
Out[48]:
In [49]:
# 복합 조건 연결식
# 여러 불린식과 여러 컬럼을 한번에 지정하기
# 1. 불린식에 이중인덱스 적용
df[ (df['Sex']=='male') & (df['Survived']==1) &
(df['Age']>50) ][['Name','Age','SibSp','Fare']].head(3)
Out[49]:
In [50]:
# 2. 불린식을 변수로 받고, 이중인덱스 적용
con1 = df['Sex']=='male'
con2 = df['Survived']==1
con3 = df['Age']>50
df[ con1&con2&con3 ][['Name','Age','SibSp','Fare']].head(3)
Out[50]:
In [51]:
# 3. ★ 불린식을 변수로 받고, loc 활용
df.loc[ con1&con2&con3, ['Name','Age','SibSp','Fare'] ].head(3)
Out[51]:
정렬, Aggregation 함수, GroupBy 적용
- DataFrame, Series의 정렬 : sort_values()
- value_counts()는 series만 됨. sort_values()는 DataFrame도 됨
- 주요 파라미터 : by, ascending, inplace
- by 특정칼럼 : 정렬기준
- ascending=True(default) : 오름차순
- ascending=False : 내림차순
- inplace=False(default) : 원본 유지, 새로운 객체 할당 필요
- inplace=True : 원본파괴
- Aggregation 함수 적용
- min(), max(), sum(), count() ... 등등
- DataFrame에서 바로 agg함수 호출 시 : 모든 칼럼에 agg 적용
- 특정 컬럼 적용 원하면 먼저 컬럼 추출 -> 뒤이어 agg 적용
- ex)df['Age','Pclass'].mean()
In [52]:
# sort_values
df_sorted = df.sort_values(by=['Name'])[['Name','Sex','Age','Pclass']]
df_sorted.head(5)
Out[52]:
In [53]:
# sort_values
df_sorted2 = df.sort_values(by=['Pclass','Name'], ascending=False)[['Name','Sex','Age','Pclass']]
df_sorted2.head(5)
Out[53]:
In [54]:
# Aggregation 함수 적용
df[['Age','Fare']].mean()
Out[54]:
groupby() 적용
- matplotlib 등 그림 그리기 전에 많이 사용함
- by에 칼럼을 입력하면 대상 칼럼으로 groupby됨
- DataFrame에 groupby()를 호출하면 DataFrameGroupBy라는 또 다른 형태의 DataFrame 반환
- agg 함수 적용하지 않으면 generator의 상태와 비슷하게..형태 바로 확인할 수 없음
- DataFrame의 groupby()에 특정칼럼만 agg를 반영하려면?
- 1.groupby먼저 적용
- 2.[ 컬럼 ] 추출 덧붙이기 -> 여러개의 컬럼일 경우 이중대괄호 주의!
- 3.agg 최종 적용
- ex) train.groupby(by='Pclass')[['Age','Fare']].mean()
In [55]:
df_group = df.groupby('Pclass').count()
df_group.head(3)
Out[55]:
In [56]:
df_group_some = df.groupby('Pclass')[['PassengerId','Survived']].count()
df_group_some
Out[56]:
In [57]:
df_group_2 = df.groupby(['Pclass','Sex'])[['PassengerId','Survived']].count()
df_group_2
Out[57]:
groupby에서 컬럼별로 다른 agg 적용하기!
- agg()의 입력 값으로 dictionary mapping을 사용
- 컬럼 : agg함수 로 매칭시킴
In [58]:
agg_format = {'Age':'max', 'SibSp':'sum', 'Fare':'mean'}
df.groupby('Pclass').agg(agg_format)
Out[58]:
결손 데이터 처리
- 결손데이터(Missing Data) : 칼럼에 값이 없는, 즉 NULL인 경우를 의미, numpy의 NaN으로 표시
- 결손데이터를 채우는 과정이 중요한 이유
- 머신러닝은 기본적으로 이 NaN값을 처리 하지 않음
- NaN 값은 평균, 총합 등의 함수 연산 시 제외됨
- NaN여부 확인 API : isna(), isnull()
- 모든 칼럼의 값이 NaN인지 아닌지를 True or False로 알려줌
- sum()과 함께 사용함
- True(Null이면) = 1
- False(Not Null이면) = 0
- NaN 값을 대체하는 (채우는) API : fillna()
- inplace=True : 원본파괴
- inplace=False(default) : 원본 비파괴, 새로운 객체에 할당 필요
In [59]:
# isna() or isnull()로 결손 데이터 여부 확인
df.isna().head(3)
Out[59]:
In [60]:
# isna()/isnull() and sum()
df.isnull().sum() # 결측치의 개수만 확인 가능
Out[60]:
In [61]:
# 'Cabin'칼럼의 결측치는 'C000'으로 채우기
# 'Age'칼럼의 결측치는 'Age'칼럼의 평균값으로 채우기
# 'Embarked'칼럼의 결측치는 'S'로 채우기
df['Cabin'].fillna('C000', inplace=True)
df['Age'].fillna(df['Age'].mean(), inplace=True)
df['Embarked'].fillna('S',inplace=True)
df.isnull().sum()
Out[61]:
apply lambda로 데이터 가공
- apply함수에 lambda식을 결합해 DataFrame이나 Series의 레코드별로 데이터를 가공
- pandas의 경우 칼럼에 일괄적으로 데이터 가공을 하는 것이 속도는 더 빠름
- 복잡한 데이터 가공이 필요한 경우에 apply lambda 사용
- lambda 입력인자 : 입력인자를 기반으로 한 계산식
- ex) lambda x : x ** 2
- lambda 식을 이용할 때, 여러 개의 값을 입력 인자로 사용해야 할 경우? map()함수를 결합!
- ex)
- a = [1,2,3]
- squares = map(lambda x:x**2, a)
- list(squares) # squares까지만 하면 class 'map' 상태임
- 결과 : [1,4,9]
In [62]:
df['Name_len'] = df['Name'].apply(lambda x:len(x)) # ['Name']칼럼의 각 value가 x에 들어감
df[['Name','Name_len']].head(3)
Out[62]:
lambda와 if else 절 복합 사용
In [63]:
df['Child_Adult'] = df['Age'].apply(lambda x:'Child' if x<=15 else 'Adult')
df[['Age','Child_Adult']].head(8)
Out[63]:
lambda 안에 if else가 두 번 이상 등장할 경우에는 별도의 함수를 만드는 것이 편리
In [64]:
# 나이에 따라 세분화된 분류를 수행하는 함수
def get_category(age):
cat=''
if age <= 5: cat = 'Baby'
elif age <= 12: cat = 'Child'
elif age <= 18: cat = 'Teenager'
elif age <= 25: cat = 'Student'
elif age <= 35: cat = 'Young Adult'
elif age <= 60: cat = 'Adult'
else: cat = 'Elderly'
return cat
# lambda식에 위에서 생성한 get_category() 함수를 반환 값으로 지정
# get_category(x)는 입력값으로 'Age'칼럼 값을 받아서 해당하는 cat 반환
df['Age_cat'] = df['Age'].apply(lambda x:get_category(x))
df[['Age','Age_cat']].head()
Out[64]:
* 출처 *
'AI Study > Machine Learning' 카테고리의 다른 글
데이터 전처리 기본 (1) - data encoding (0) | 2021.11.21 |
---|---|
sklearn의 model selction module (데이터셋 분리 및 교차검증) (0) | 2021.09.06 |
sklearn 기반 프레임워크 살펴보기 (0) | 2021.09.06 |
머신러닝을 위한 Numpy 기초 (0) | 2021.08.23 |
Python 기반의 머신러닝 생태계 이해하기 (0) | 2021.08.23 |