|
AICE
라이브러리 임포트
# pandas import
import sklearn as sk
import pandas as pd
import numpy as np
!pip install seaborn
import seaborn as sns
import matplotlib.pyplot as plt
AIDU에서 필요시
from aicentro.session import Session
from aicentro.framework.tensorflow import Tensorflow as AiduFrm
필요시
# !pip install Ipython
from IPython.display import Image
# 진행상황을 체크할 수 있는 라이브러리
!pip install tqdm
데이터 불러오기+ 합치기
concat합치기
df = pd.read_csv("onenavi_train.csv",sep="|") #파일명, sep 주의
df_eval = pd.read_csv("onenavi_evaluation.csv",sep="|")
df_total=pd.concat([df,df_eval],ignore_index=True)
df_total #데이터 확인
merge합치기 on 기준으로 합치기
df_pnu = pd.read_csv("onenavi_pnu.csv",sep="|") # 주소(시도/시군구 정보)
df_signal = pd.read_csv("onenavi_signal.csv",sep="|") # 경로의 신호등 갯수
df_total=pd.merge(df_total,df_pnu , on="RID")
df_total=pd.merge(df_total,df_signal , on="RID")
df_total
#AIDU에서 필요시 데이터 셋 로딩
aicentro_session = Session(verify = False)
aidu_framework = AiduFrm(session = aicentro_session)
df = pd.read_csv(aidu_framework.config.data_dir + "/onenavi_train.csv", sep = "|")
df_eval = pd.read_csv(aidu_framework.config.data_dir + "/onenavi_evaluation.csv", sep = "|")
# 학습/평가 데이터의 전처리 기준을 통일하기위해 데이터 합본
df_total=pd.concat([df,df_eval],ignore_index=True)
1-1. DataFrame 만들어 보기
Dictionary 형으로 생성
a1 = pd.DataFrame({"a" : [1,2,3], "b" : [4,5,6], "c" : [7,8,9]})
a1
1-2. 파일을 읽어서 DataFrame생성하기
# kt 데이터 파일을 활용
# 파일을 수정하고 저장 자체를 MS Office에서 하여서 encoding을 cp949로 해주어야 함
CSV파일 읽는 법
cust = pd.read_csv('./sc_cust_info_txn_v1.5.csv', encoding = "cp949")
cust
jason 파일 읽는법1 판다스로 읽기
df = pd.read_json('test.json')
jason 파일 읽는법2 jason import
import pandas as pd
import json
with open('test.json') as f:
js = json.loads(f.read())
df = pd.DataFrame(js)
1-3. 데이터 살펴보기
# 상위 3개
cust.head(n=3)
#하위 10개
cust.tail(n=10)
# shape : 데이터를 파악하는데 중요함
cust.shape
# DataFrame의 columns들을 보여줌
cust.columns
# 데이터 타입 및 각 아이템등의 정보를 보여줌
cust.info()
# DataFrame의 기본적인 통계정보를 보여줌
cust.describe()
# DataFrame의 데이터 종류
cust.dtypes
#참고
df_total['level1_pnu_x'].values() #그 컬럼 값 순서대로. 중복 있음
df_total['level1_pnu_x'].unique() #중복 없이, 포함된 값만 보여줌
1-4. read_csv 함수 파라미터 살펴보기 파일 불러오기 파라미터
함수에 커서를 가져다 두고 shift+tab을 누르면 해당 함수의 parameter 볼 수 있음
sep - 각 데이터 값을 구별하기 위한 구분자(separator) 설정
index_col : index로 사용할 column 설정
usecols : 실제로 dataframe에 로딩할 columns만 설정
usecols은 index_col을 포함하여야 함
# 참고
df = pd.read_csv("onenavi_train.csv", sep = "|")
cust2 = pd.read_csv('./sc_cust_info_txn_v1.5.csv', index_col='cust_class', usecols=['cust_class', 'r3m_avg_bill_amt', 'r3m_B_avg_arpu_amt', 'r6m_B_avg_arpu_amt'])
cust2
2. Data 조회하기
1-1. 데이터 추출하기
1) column 선택하기 (series 형태)
cust.cust_class = cust['cust_class']
cust.cust_class
# cf : series 형태로 가지고 오기(cust.cust_class = cust['cust_class'])
cust['cust_class'] #위와 동일
# cf : Dataframe형태로 가지고 오기 데이터프레임 형태로 가져오기.
cust[['cust_class']]
3) 복수의 컬럼 선택하기
# 'cust_class' , 'age' 'r3m_avg_bill_amt'등 3개의 col 선택하기
cust[['cust_class', 'age', 'r3m_avg_bill_amt']]
4) DataFrame slicing 슬라이싱
특정 행 범위를 가지고 오고 싶다면 [ ]를 사용
# 7,8,9행을 가지고 옴 (인덱스 기준)
cust[7:10]
5) row 선택하기
DataFrame에서는 기본적으로 [ ]을 사용하여 column을 선택
row 선택(두가지 방법이 존재)
loc : Dataframe에 존재하는 인덱스를 그대로 사용 (인덱스 기준으로 행 데이터 읽기)
iloc : Datafrmae에 존재하는 인덱스 상관없이 0 based index로 사용 (행 번호 기준으로 행 데이터 읽기)
이 두 함수는 ,를 사용하여 column 선택도 가능
# arange함수는 10부터 19에서 끝나도록 간격을 1로 반환한다.
cp=np.arange(10,20)
cp
#index를 100부터 달아주기
cust.index = np.arange(100, 10030)
cust
#한개의 row만 가지고 오기
cust.loc[[289]]
#여러개의 row 가지고 오기
cust.loc[[102, 202, 302]] #loc은 인덱스 글자 그대로
#iloc과비교(위와 같은 값을 가지고 오려면...) (직접 타이핑 해보세요)
cust.iloc[[2, 102, 202]] #iloc은 인덱스 위치에 있는 숫자 가져오기. Ex 0,1,2번째 숫자 “100,101,102”
#row, column 동시에 선택하기
#loc, iloc 속성을 이용할 때, 콤마를 이용하여 row와 col 다 명시 가능
# 100, 200, 300 대상으로 cust_class, sex_type, age, r3m_avg_bill_amt, r3m_A_avg_arpu_amt col 가지고 오기(loc사용)
cust.loc[[100, 200, 300], ['cust_class', 'sex_type', 'age', 'r3m_avg_bill_amt', 'r3m_A_avg_arpu_amt']] # loc[[row], [col]]
# 같은 형태로 iloc사용하기 (index를 level로 가지고 오기) #column도 index번호로
# 100, 200, 300 대상으로 cust_class, sex_type, age, r3m_avg_bill_amt, r3m_A_avg_arpu_amt col 가지고 오기(iloc사용)
cust.iloc[[0, 100, 200], [3, 4, 5, 9, 10]]
6) boolean selection 연산으로 row 선택하기 (= 컬럼 조건문으로 행 추출하기)
해당 조건에 맞는 row만 선택
조건을 명시하고 조건을 명시한 형태로 inedxing 하여 가지고 옴
ex: 남자이면서 3개월 평균 청구 금액이 50000 이상이면서 100000 미만인 사람만 가지고오기
방법1
#조건을 전부다 [ ]안에 넣어 주면 됨
extract = cust[(cust['sex_type']=='M') & (cust['r3m_avg_bill_amt']>=50000) & (cust['r3m_avg_bill_amt']< 100000)]
extract.head()
방법2
# 조건문이 너무 길어지거나 복잡해지면...아래와 같은 방식으로 해도 무방함
# 남자이면서 # 3개월 평균 청구 금액이 50000 이상이면서 100000 미만
sex = cust['sex_type']=='M'
bill = (cust['r3m_avg_bill_amt']>=50000) & (cust['r3m_avg_bill_amt']< 100000)
cust[sex & bill].head()
#참고! 그 컬럼에 필요한 데이터만 남기기
df_total=df_total[(df_total['level1_pnu_x']=='서울특별시')|(df_total['level1_pnu_x']=='경기도')|(df_total['level1_pnu_x']=='인천광역시')]
df_total=df_total.reset_index(drop=True)
df_total
1-2. 데이터 추가하기
1) 새 column 추가하기 열 추가
데이터 전처리 과정에서 빈번하게 발생하는 것
# r3m_avg_bill_amt 두배로 새로운 col만들기 #맨끝에 만들어짐
cust['r3m_avg_bill_amt2'] = cust['r3m_avg_bill_amt'] * 2 #새로 컬럼값입력
cust.head()
cust['r3m_avg_bill_amt3'] = cust['r3m_avg_bill_amt2'] + cust['r3m_avg_bill_amt']
cust.head()
insert 함수 사용하여 원하는 위치에 추가하기
# 새로은 col들은 항상맨뒤에 존재 원하는 위치에 col을 추가하고자 하는 경우
# 위치를 조절 하고 싶다면(insert함수 사용)
cust.insert(10, 'r3m_avg_bill_amt10', cust['r3m_avg_bill_amt'] *10) # 0부터 시작하여 10번째 col에 insert
cust.head()
2) column 삭제하기 열 삭제
drop 함수 사용하여 삭제
axis는 삭제를 가로(행)기준으로 할 것인지, 세로(열)기준으로 할 것인지 명시하는 'drop()'메소드의 파라미터임
리스트를 사용하면 멀티플 col 삭제 가능
# axis : dataframe은 차원이 존재 함으로 항상 0과 1이 존재
# 0은 행레벨, 1을 열 레벨(아래방향) #drop은 원본데이터에서 지워지는건 아님.!!
cust.drop('r3m_avg_bill_amt10', axis=1)
# 원본 데이터를 지우고자 한다면...
# 방법1 : 데이터를 지우고 다른 데이터 프레임에 저장
#단 cust는 원본이 남아있음
cust1=cust.drop('r3m_avg_bill_amt10', axis=1)
cust1.head()
# 방법 2 : inplace 파라미터를 할용 True인 경우 원본데이터에 수행
cust.drop('r3m_avg_bill_amt10', axis=1, inplace=True)
Chapter 2. Pandas 이해 및 활용
DataFrame 변형하기
1. group by 이해하기
1-1. 데이터 묶기
# pandas import 임포트하기
import pandas as pd
import numpy as np
# !pip install Ipython
from IPython.display import Image
1)그룹화(groupby)
1-1) groupby의 groups 속성
각 그룹과 그룹에 속한 index를 dict 형태로 표현
# 파라미터 값으로 col의 리스트나 col을 전달
# 출력은 우선 dataframe이라고 하는 객체임(그룹을 생성까지 한 상태)
gender_group = cust.groupby('sex_type')
gender_group <--- 이건 의미없고
#그룹에 잘 들어왔는지 보려면 groups
# groups를 활용하여 그룹의 속성을 살펴보기
gender_group.groups
1-2) groupby 내부 함수 활용하기
그룹 데이터에 적용 가능한 통계 함수(NaN은 제외하여 연산)
count : 데이터 개수
size : 집단별 크기
sum : 데이터의 합
mean, std, var : 평균, 표준편차, 분산
min, max : 최소, 최대값
#그룹으로 된 곳에서 각 컬럼 조회
# count 함수 확인
gender_group.count()
# mean 함수 확인
gender_group.mean()
# max값 확인하기
gender_group.max()
# 특정 col만 보는 경우 : gender별 r3m_avg_bill_amt의 평균
gender_group.mean()[['r3m_avg_bill_amt']]
1-3) 인덱스 설정(groupby) 후 데이터 추출하기
성별 r3m_avg_bill_amt의 평균
# groupby한 상태에서 가지고 오는 경우
gender_group.mean()[['r3m_avg_bill_amt']]
# groupby하기 전 원 DataFrame에서 가지고 오는 경우(위와 같음)
cust.groupby('sex_type').mean()[['r3m_avg_bill_amt']]
1-4) 복수 columns을 기준으로 Groupping 하기
groupby에 column 리스트를 전달할 수 있고 복수개의 전달도 가능함
통계함수를 적용한 결과는 multiindex를 갖는 DataFrame
# cust_class 와 sex_type으로 index를 정하고 이에따른 r3m_avg_bill_amt의 평균을 구하기
cust.groupby(['cust_class', 'sex_type']).mean()[['r3m_avg_bill_amt']]
# 위와 동일하게 groupby한 이후에 평균 구하기
multi_group=cust.groupby(['cust_class', 'sex_type'])
multi_group.mean()[['r3m_avg_bill_amt']]
# INDEX는 DEPTH가 존재함 (loc을 사용하여 원하는 것만 가지고 옴)
cust.groupby(['cust_class', 'sex_type']).mean().loc[[("D","M")]] #행을 선택하는 경우
1-5) index를 이용한 group by
index가 있는 경우, groupby 함수에 level 사용 가능
level은 index의 depth를 의미하며, 가장 왼쪽부터 0부터 증가
set_index 함수
column 데이터를 index 레벨로 변경하는 경우 사용
기존의 행 인덱스를 제거하고 데이터 열 중 하나를 인덱스로 설정
reset_index 함수
인덱스 초기화
기존의 행 인덱스를 제거하고 인덱스를 데이터 열로 추가
# heat DataFrame 다시 한번 확인 합니다.
cust.head()
1-6) MultiIndex를 이용한 groupping
# set_index로 index셋팅(멀티도 가능)
cust.set_index(['cust_class','sex_type'])
# reset_index활용하여 기존 DataFrame으로 변환 (set_index <-> reset_index) #인덱스 다시 원상복구
cust.set_index(['cust_class','sex_type']).reset_index()
# 멀티 인덱스 셋팅 후 인덱스 기준으로 groupby하기
# 'sex'와 'cp'를 기준으로 index를셋팅하고 index를 기준으로 groupby하고자 하는경우
# groupby의 level은 index가 있는 경우에 사용
cust.set_index(['cust_class','sex_type']).groupby(level=[0]).mean() #이미 0,1('cust_class','sex_type') 레벨인데 0('cust_class')만보겠다
cust.set_index(['cust_class','sex_type']).groupby(level=[0,1]).mean() #0,1레벨 모두 보겠다
1-7) aggregate(집계) 함수 사용하기
groupby 결과에 집계함수를 적용하여 그룹별(mean, max등) 데이터 확인 가능
#그룹별로 한번에 데이터를 한번에 보는 경우 #aggregate는 그 컬럼내 데이터 적용
cust.set_index(['cust_class','sex_type']).groupby(level=[0,1]).aggregate([np.mean, np.max])
2. pivot / pivot_table 함수 활용
2-1. pivot 은 뭘까?
dataframe의 형태를 변경
여러 분류로 섞인 행 데이터를 열 데이터로 회전 시키는 것
pivot의 사전적의미 : (축을 중심으로)회전하다, 회전시키다.
pivot형태 : pandas.pivot(index, columns, values) 로 사용할 컴럼을 명시
#자료 실습용 예시
data = pd.DataFrame({'cust_id': ['cust_1', 'cust_1', 'cust_1', 'cust_2', 'cust_2', 'cust_2', 'cust_3', 'cust_3', 'cust_3'],
'prod_cd': ['p1', 'p2', 'p3', 'p1', 'p2', 'p3', 'p1', 'p2', 'p3'],
'grade' : ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B'],
'pch_amt': [30, 10, 0, 40, 15, 30, 0, 0, 10]})
data
# 행(row)는 고객ID(cust_id), 열(col)은 상품코드(prod_cd), 값은 구매금액(pch_amt)을 pivot를 활용하여 만들어보기
data.pivot(index = 'cust_id', columns ='prod_cd', values ='pch_amt')
data.pivot('cust_id', 'prod_cd', 'pch_amt') #index라는 표현이 없어도 동일한 효과
2-2. Pivot_table은 뭘까? Pivot이 할수 없는 aggfunc을 이용해 계산가능
pivot_table형태 : pandas.pivot_table(data, index, columns, aggfunc)
# pivot_table을 활용하여 위와 동일하게 만들기
data.pivot_table(index = 'cust_id', columns ='prod_cd', values ='pch_amt')
#동일
2-3. Pivot과 Pivot_table의 차이는뭘까 ?
pivot은 안되고 pivot_table만을 사용해야 하는 경우가 있음
1) index가 2개 이상인 경우 #pivot은 계산안됨, Pivot table은 계산됨
실습 VOD 동영상에서는 아래 코드 실행시 에러가 발생하지만
저희 실습은 Pandas 버젼업 되어 에러없이 아래 코드가 실행됩니다.
data.pivot(index = ['cust_id','grade'], columns ='prod_cd', values ='pch_amt') #오류
data.pivot_table(index = ['cust_id','grade'], columns ='prod_cd', values ='pch_amt')
2) columns가 2개 이상인 경우
실습 VOD 동영상에서는 아래 코드 실행시 에러가 발생하지만
저희 실습은 Pandas 버젼업 되어 에러없이 아래 코드가 실행됩니다.
data.pivot(index = 'cust_id', columns =['grade','prod_cd'], values ='pch_amt') #에러, (뉴버전 에러안남)
data.pivot_table(index = 'cust_id', columns =['grade','prod_cd'], values ='pch_amt')
3) 중복 값이 있는 경우
pivot은 중복 값이 있는 경우 valueError를 반환함
pivot_table은 aggregation 함수를 활용하여 처리
#index로 쓰인 grade가 중복이 있음
data.pivot(index='grade', columns='prod_cd', values='pch_amt') #오류남
#index로 쓰인 grade가 중복이 있음
data.pivot_table(index='grade', columns='prod_cd', values='pch_amt')
2-4. pivot_table의 추가 살펴 보기
pivot_table은 aggregation 함수를 활용하여 처리
#affgunc는 기본적으로 평균
# aggfunc를 sum으로 구하기 (직접 타이핑 해보세요)
data.pivot_table(index='grade', columns='prod_cd', values='pch_amt', aggfunc=np.sum)
# 위와 같은결과(참고로 알아 두셔요)
pd.pivot_table(data, index='grade', columns='prod_cd', values='pch_amt', aggfunc=np.sum)
# aggfunc를 mean으로 구하기(default가 mean임) (직접 타이핑 해보세요)
data.pivot_table(index='grade', columns='prod_cd', values='pch_amt', aggfunc=np.mean)
3. stack, unstack 함수 활용
df = pd.DataFrame({
'지역': ['서울', '서울', '서울', '경기', '경기', '부산', '서울', '서울', '부산', '경기', '경기', '경기'],
'요일': ['월요일', '화요일', '수요일', '월요일', '화요일', '월요일', '목요일', '금요일', '화요일', '수요일', '목요일', '금요일'],
'강수량': [100, 80, 1000, 200, 200, 100, 50, 100, 200, 100, 50, 100],
'강수확률': [80, 70, 90, 10, 20, 30, 50, 90, 20, 80, 50, 10]})
df
3-1. stack & unstack
stack : 컬럼 레벨에서 인덱스 레벨로 dataframe 변경
즉, 데이터를 row 레벨로 쌓아올리는 개념으로 이해하면 쉬움
unstack : 인덱스 레벨에서 컬럼 레벨로 dataframe 변경
stack의 반대 operation
#둘은 역의 관계에 있음
#보여지는 것만 바뀜.
# '지역'과 '요일'두개로 인덱스를 설정하고 별도의 DataFrame으로 설정 하기 - (직접 타이핑 해보세요)
new_df = df.set_index(['지역', '요일'])
new_df #지역이 0번쨰 인덱스, 요일이 1번째 인덱스)
# 첫번째 레벨의 인덱스(지역)를 컬럼으로 이동 / 인덱스도 레벨이 있음
new_df.unstack(0)
# 두번째 레벨의 인덱스를 컬럼으로 이동
new_df.unstack(1) #원래 0번쨰 인덱스는 다시 그대로.
new_df # 원데이터 다시 볼수 있음.
# new_df.unstack(0)상태에서 첫번째 레벨의 컬럼(강수량과 강수확률)을 인덱스로 이동(stack(0))
new_df.unstack(0).stack(0)
Chapter 2. Pandas 이해 및 활용
DataFrame 병합하기
1. concat함수 활용
두 개 이상의 데이터프레임을 하나로 합치는 데이터 병합(merge)이나 연결(concatenate)을 지원합니다.
# pandas import
import pandas as pd
import numpy as np
# !pip install Ipython
from IPython.display import Image
1-1. concat 함수 사용하여 DataFrame 병합하기
pandas.concat 함수 (배열결합 : concatenate)
데이터의 속성 형태가 동일한 데이터 셋 끼리 합칠때 사용 (DataFrame을 물리적으로 붙여주는 함수)
열 or 행 레벨로 병합하는 것
1) column명이 같은 경우
ignore_index, axis 활용
df1 = pd.DataFrame({'key1' : [0,1,2,3,4], 'value1' : ['a', 'b', 'c','d','e']}, index=[0,1,2,3,4])
df2 = pd.DataFrame({'key1' : [3,4,5,6,7], 'value1' : ['c','d','e','f','g']}, index=[3,4,5,6,7])
df1
key1 value1
0 0 a
1 1 b
2 2 c
3 3 d
4 4 e
df2
key1 value1
3 3 c
4 4 d
5 5 e
6 6 f
7 7 g
concat함수 옵션
ignore_index : 기존 index를 무시하고자 하는 경우
False : 기존 index유지(default) / True : 기존 index무시(index재배열)
axis
0 : 위+아래로 합치기(row레벨) / 1 : 왼쪽+오른쪽으로 합치기(col레벨)
# ignore_index에 대한이해 (직접 타이핑 해보세요)
#true 중복상관없이 모두 보여주기
pd.concat([df1, df2], ignore_index=False)
key1 value1
0 0 a
1 1 b
2 2 c
3 3 d
4 4 e
3 3 c
4 4 d
5 5 e
6 6 f
7 7 g
# ignore_index에 대한이해 (직접 타이핑 해보세요)
#true 중복값 삭제
pd.concat([df1, df2], ignore_index=True)
key1 value1
0 0 a
1 1 b
2 2 c
3 3 d
4 4 e
5 3 c
6 4 d
7 5 e
8 6 f
9 7 g
# axis=0,1 비교해 보기 (직접 타이핑 해보세요)
pd.concat([df1, df2], axis =1) #컬럼을 기준으로
key1 value1 key1 value1
0 0.0 a NaN NaN
1 1.0 b NaN NaN
2 2.0 c NaN NaN
3 3.0 d 3.0 c
4 4.0 e 4.0 d
5 NaN NaN 5.0 e
6 NaN NaN 6.0 f
7 NaN NaN 7.0 g
# axis=0,1 비교해 보기 (직접 타이핑 해보세요)
pd.concat([df1, df2], axis =0) #열 값을 기준으로
key1 value1
0 0 a
1 1 b
2 2 c
3 3 d
4 4 e
3 3 c
4 4 d
5 5 e
6 6 f
7 7 g
2) column명이 다른 경우 join 파라미터
concat함수중에 join에 대한이해
join 방식은 outer의 경우 합집합, inner의 경우 교집합을 의미
df3 = pd.DataFrame({'a':['a0','a1','a2', 'a3'], 'b':['b0','b1','b2','b3'], 'c':['c0','c1','c2','c3']}, index = [0,1,2,3])
df4 = pd.DataFrame({'a':['a2','a3','a4', 'a5'], 'b':['b2','b3','b4','b5'], 'c':['c2','c3','c4','c5'], 'd':['d1','d2','d3','d4']}, index = [2,3,4,5])
df3
a b c
0 a0 b0 c0
1 a1 b1 c1
2 a2 b2 c2
3 a3 b3 c3
df4
a b c d
2 a2 b2 c2 d1
3 a3 b3 c3 d2
4 a4 b4 c4 d3
5 a5 b5 c5 d4
pd.concat([df3, df4], join='outer') #합집합형태
a b c d
0 a0 b0 c0 NaN
1 a1 b1 c1 NaN
2 a2 b2 c2 NaN
3 a3 b3 c3 NaN
2 a2 b2 c2 d1
3 a3 b3 c3 d2
4 a4 b4 c4 d3
5 a5 b5 c5 d4
pd.concat([df3, df4], join='inner') #교집합형태
a b c
0 a0 b0 c0
1 a1 b1 c1
2 a2 b2 c2
3 a3 b3 c3
2 a2 b2 c2
3 a3 b3 c3
4 a4 b4 c4
5 a5 b5 c5
3) index 중복 여부 확인
concat함수중에 verify_integrity에 대한 이해
verify_integrity=False가 default임으로 error발생을 하지 않음
verify_integrity=True인 경우 error 발생
df5 = pd.DataFrame({'A':['A0','A1','A2'], 'B':['B0','B1','B2'], 'C':['C0','C1','C2'], 'D':['D0','D1','D2']}, index=['I0','I1','I2'])
df6 = pd.DataFrame({'A':['AA2','A3','A4'], 'B':['BB2','B3','B4'], 'C':['CC2','C3','C4'], 'D':['DD2','D3','D4']}, index=['I2','I3','I4'])
df5
A B C D
I0 A0 B0 C0 D0
I1 A1 B1 C1 D1
I2 A2 B2 C2 D2
df6
A B C D
I2 AA2 BB2 CC2 DD2
I3 A3 B3 C3 D3
I4 A4 B4 C4 D4
pd.concat([df5, df6], verify_integrity=False) #false는 중복값에 에러 안남
A B C D
I0 A0 B0 C0 D0
I1 A1 B1 C1 D1
I2 A2 B2 C2 D2
I2 AA2 BB2 CC2 DD2
I3 A3 B3 C3 D3
I4 A4 B4 C4 D4
# true는 index중복이있는 경우 error가 남
pd.concat([df5, df6], verify_integrity=True)
---------------------------------------------------------------------------
ValueError: Indexes have overlapping values: Index(['I2'], dtype='object')
----
2. merge & join 함수 활용
2-1. DataFrame merge
Database의 Table들을 Merge/Join하는 것과 유사함
특정한 column(key)을 기준으로 병합
join 방식: how 파라미터를 통해 명시(특정한 col을 바탕으로 join 하는 것)
inner: 기본 merge방법, 일치하는 값이 있는 경우 (Merge할 테이블의 데이터가 모두 있는 경우만 가지고 옴) #inner방식이 디폴트
left: left outer join (왼쪽을 기준으로 오른쪽을 채움 - 오른쪽에 데이터 없으면 NaN)
right: right outer join
outer: full outer join (Left와 Right를 합한 것)
customer = pd.DataFrame({'cust_id' : np.arange(6),
'name' : ['철수', '영희', '길동', '영수', '수민', '동건'],
'나이' : [40, 20, 21, 30, 31, 18]})
orders = pd.DataFrame({'cust_id' : [1, 1, 2, 2, 2, 3, 3, 1, 4, 9],
'item' : ['치약', '칫솔', '이어폰', '헤드셋', '수건', '생수', '수건', '치약', '생수', '케이스'],
'quantity' : [1, 2, 1, 1, 3, 2, 2, 3, 2, 1]})
customer
cust_id name 나이
0 0 철수 40
1 1 영희 20
2 2 길동 21
3 3 영수 30
4 4 수민 31
5 5 동건 18
orders
cust_id item quantity
0 1 치약 1
1 1 칫솔 2
2 2 이어폰 1
3 2 헤드셋 1
4 2 수건 3
5 3 생수 2
6 3 수건 2
7 1 치약 3
8 4 생수 2
9 9 케이스 1
1) merge함수의 on 옵션
join 대상이 되는 column 명시
# 기본적인 Merge방식은 inner임 (직접 타이핑 해보세요)
# customer의 cust_id 5번과 orders의 cust_id 9번이 없는 것을 확인
# merge하고자 하는 컬럼 명칭을 on에 명시한다.
pd.merge(customer, orders, on='cust_id') #inner방식이 디폴트 (일치하는 값이 있는 경우에만 합친다)
cust_id name 나이 item quantity
0 1 영희 20 치약 1
1 1 영희 20 칫솔 2
2 1 영희 20 치약 3
3 2 길동 21 이어폰 1
4 2 길동 21 헤드셋 1
5 2 길동 21 수건 3
6 3 영수 30 생수 2
7 3 영수 30 수건 2
8 4 수민 31 생수 2
#cust_id 5번과 9번이 없어짐. #기본이inner라서
# 여러개인 경우 리스트 일치하는 것만 가지고 옴
pd.merge(customer, orders, on='cust_id', how='inner')
cust_id name 나이 item quantity
0 1 영희 20 치약 1
1 1 영희 20 칫솔 2
2 1 영희 20 치약 3
3 2 길동 21 이어폰 1
4 2 길동 21 헤드셋 1
5 2 길동 21 수건 3
6 3 영수 30 생수 2
7 3 영수 30 수건 2
8 4 수민 31 생수 2
#위와 동일
# 왼쪽 테이블을 기준으로 Merge (여기서는 customer기준)
pd.merge(customer, orders, on='cust_id', how='left')
cust_id name 나이 item quantity
0 0 철수 40 NaN NaN
1 1 영희 20 치약 1.0
2 1 영희 20 칫솔 2.0
3 1 영희 20 치약 3.0
4 2 길동 21 이어폰 1.0
5 2 길동 21 헤드셋 1.0
6 2 길동 21 수건 3.0
7 3 영수 30 생수 2.0
8 3 영수 30 수건 2.0
9 4 수민 31 생수 2.0
10 5 동건 18 NaN NaN
#왼쪽 데이터 customer에 있는 5번이 나옴
# 오른쪽 테이블을 기준으로 Merge (여기서는 orders기준)
pd.merge(customer, orders, on='cust_id', how='right')
cust_id name 나이 item quantity
0 1 영희 20.0 치약 1
1 1 영희 20.0 칫솔 2
2 2 길동 21.0 이어폰 1
3 2 길동 21.0 헤드셋 1
4 2 길동 21.0 수건 3
5 3 영수 30.0 생수 2
6 3 영수 30.0 수건 2
7 1 영희 20.0 치약 3
8 4 수민 31.0 생수 2
9 9 NaN NaN 케이스 1
#오른쪽 orders의 데이터의 9번이 나옴
# outer : Left와 Right를 합친 것 #합집합의 개념
pd.merge(customer, orders, on='cust_id', how='outer')
cust_id name 나이 item quantity
0 0 철수 40.0 NaN NaN
1 1 영희 20.0 치약 1.0
2 1 영희 20.0 칫솔 2.0
3 1 영희 20.0 치약 3.0
4 2 길동 21.0 이어폰 1.0
5 2 길동 21.0 헤드셋 1.0
6 2 길동 21.0 수건 3.0
7 3 영수 30.0 생수 2.0
8 3 영수 30.0 수건 2.0
9 4 수민 31.0 생수 2.0
10 5 동건 18.0 NaN NaN
11 9 NaN NaN 케이스 1.0
2) index 기준으로 join하기
#cust_id를 기준으로 인덱스 생성하기 (set_index활용) (직접 타이핑 해보세요)
cust1 = customer.set_index('cust_id')
order1 = orders.set_index('cust_id') #데이터를 index형태로 별도로 생성
cust1
name 나이
cust_id
0 철수 40
1 영희 20
2 길동 21
3 영수 30
4 수민 31
5 동건 18
order1
item quantity
cust_id
1 치약 1
1 칫솔 2
2 이어폰 1
2 헤드셋 1
2 수건 3
3 생수 2
3 수건 2
1 치약 3
4 생수 2
9 케이스 1
# on을 명시할 필요 없이 index를 merge 하고자 하는 경우
pd.merge(cust1, order1, left_index=True, right_index=True)
#inner와 동일한 형태
name 나이 item quantity
cust_id
1 영희 20 치약 1
1 영희 20 칫솔 2
1 영희 20 치약 3
2 길동 21 이어폰 1
2 길동 21 헤드셋 1
2 길동 21 수건 3
3 영수 30 생수 2
3 영수 30 수건 2
4 수민 31 생수 2
##Index에 5번 9번 없음. 기본이 inner방식이기 때문에
연습문제1) 가장 많이 팔린 아이템은?
Hint : merge, groupby, sort_values 활용
아이템이 중요함으로 orders DF이 중요
# 1. customer, orders 를 merge (how는?)
# 2. group_by이용하여 item 을 grouping후 sum
#item기준이기 때문에 orders 가 기준. 따라서 on=’cust_id’
pd.merge(customer, orders, on='cust_id', how='right').groupby('item').sum()
cust_id 나이 quantity
item
생수 7 61.0 4
수건 5 51.0 5
이어폰 2 21.0 1
치약 2 40.0 4
칫솔 1 20.0 2
케이스 9 0.0 1
헤드셋 2 21.0 1
# 3. sort_values를 이용하여 quantity를기준으로 sort + 내림차순으로 정렬
pd.merge(customer, orders, on='cust_id', how='right').groupby('item').sum().sort_values(by='quantity', ascending=False) #quantity기준으로 내림차순
cust_id 나이 quantity
item
수건 5 51.0 5
생수 7 61.0 4
치약 2 40.0 4
칫솔 1 20.0 2
이어폰 2 21.0 1
케이스 9 0.0 1
헤드셋 2 21.0 1
연습문제2) 영희가 가장 많이 구매한 아이템은?
1.우선 사람과 아이템 별로 sum을 해서(groupby시 "이름"과 "아이템"기준으로 합을 구하고)
2.loc을 활용하여 (영희의 row의 quantity만 확인)
#영희가 들어가야 하니까 customer기준으로
pd.merge(customer, orders, on='cust_id', how='inner').groupby(['name', 'item']).sum()
cust_id 나이 quantity
name item
길동 수건 2 21 3
이어폰 2 21 1
헤드셋 2 21 1
수민 생수 4 31 2
영수 생수 3 30 2
수건 3 30 2
영희 치약 2 40 4
칫솔 1 20 2
pd.merge(customer, orders, on='cust_id', how='inner').groupby(['name', 'item']).sum().loc['영희']
cust_id 나이 quantity
item
치약 2 40 4
칫솔 1 20 2
2-2. join 함수
index가 있는 경우 사용(행 인덱스를 기준으로 결합)
내부적으로 pandas.merge 함수를 기반으로 만들어짐
기본적으로 index를 사용하여 left join
형태 : Dataframe1.join(Dataframe2. how='left')
cust1.join(order1, how='inner') #cust1, order1은 인덱스로 이미 변환한 데이터
name 나이 item quantity
cust_id
1 영희 20 치약 1
1 영희 20 칫솔 2
1 영희 20 치약 3
2 길동 21 이어폰 1
2 길동 21 헤드셋 1
2 길동 21 수건 3
3 영수 30 생수 2
3 영수 30 수건 2
4 수민 31 생수 2
|