본문 바로가기
개발일지/Pandas

pandas 판다스 기초 18 merge, join, fillna, drop

by 다니엘의 개발 이야기 2022. 8. 8.
320x100

이번에도 호흡은 길다.

하지만 원리가 생각보다 단조로워서 어렵진 않았다.

다만, 흐름이 끊길일들이 너무 많았다.

대표적으로 허벅지를 고름이 많이 고여있어서 새끼손가락 반마디만큼 째고,

아직도 곪아있는게 남아있다는 이유로 1주일이 넘게 꼬매지 않고 있다;

이런일이 실제로 있을 줄이야...

걸을때마다 다리 안에서 벌레가 기어다니는 느낌이다..

 

아무튼! 본론으로 돌아와서!

# Merging, Joining and Concatenating DataFrames
## Adding / concatenating Rows (Part 1)

import pandas as pd

men2004 = pd.read_csv('men2004.csv')
men2004.head()

'''
Athlete	Medals
0	PHELPS, Michael	8
1	THORPE, Ian	4
2	SCHOEMAN, Roland	3
3	PEIRSOL, Aaron	3
4	CROCKER, Ian	3
'''
men2008 = pd.read_csv('men2008.csv')
men2008.head()

'''
Athlete	Medals
0	PHELPS, Michael	8
1	LOCHTE, Ryan	4
2	BERNARD, Alain	3
3	SULLIVAN, Eamon	3
4	LAUTERSTEIN, Andrew	3
'''
# 2004년 데이터프레임에 2008년의 모든 데이터프레임을 이어붙이기
# 방법1 append

men2004.append(men2008, ignore_index= True)
# 2004년 데이터프레임에 2008년의 모든 데이터프레임을 이어붙이기
# 방법2 concat

pd.concat([men2004, men2008], ignore_index = True, keys = None)

# axis의 기본값이 0 즉, 행(가로)을 기준으로 설정되어있다.
# 만약 axis를 1롤 설정해준다면 열(세로)를 기준으로 설정되기 때문에
# A라는 데이터 프레임의 마지막을 기준으로 오른쪽으로 B라는 데이터 프레임을 붙이는 것이 가능하다.
# concat에서 keys는 메인 행 인덱스를 구분해주는 역할을 한다.
# 따라서 이걸 잘 써주면, ignore_index가 필요가 없다.
pd.concat([men2004, men2008], keys = [2004,2008])

'''
		Athlete	Medals
2004	0	PHELPS, Michael	8
        1	THORPE, Ian	4
...	...	...	...
2008	60	MALLET, Gregory	1
        61	ZHANG, Lin	1
        121 rows × 2 columns
'''
# 즉, 뿌리, 줄기의 통계 개념과 같이 keys는 뿌리를 만들어주는 역할을 한다.
# 뿌리와 줄기개념은 '멀티 인덱스'라고 불린다.
# 만약, 뿌리별로 행 인덱스값이 1~마지막, 다음 뿌리에서 1~ 마지막이 되길 원한다면 ignore_index를 안써줘도 된다.
# 하지만 뿌리별로 구분이 되더라도, 전체 행 인덱스 값은 통일해서 1부터 마지막까지 원큐에 가길 원한다면 ignore_index = True를 해줘야한다.
# 고 생각할 수 있다.
pd.concat([men2004, men2008], ignore_index = True, keys = [2004, 2008])

# 하지만 이와같이 ignore_index = True를 해주면 keys에 입력된 값은 무용지물이 된다.

'''
    Athlete	Medals
0	PHELPS, Michael	8
1	THORPE, Ian	4
...	...	...
119	MALLET, Gregory	1
120	ZHANG, Lin	1
121 rows × 2 columns
'''
men0408 = pd.concat([men2004,men2008], ignore_index = False, keys = [2004,2008], names = ['Year'])

'''

                Athlete	Medals
Year			
2004	0	PHELPS, Michael	8
        1	THORPE, Ian	4
...	...	...	...
2008	60	MALLET, Gregory	1
        61	ZHANG, Lin	1
121 rows × 2 columns
'''

# 멀티인덱스 및 keys를 작동시키려면 ignore_index 를 False로 주거나, 아예 입력을 하지 말아야지 작동됨을 명심하자.
men0408

'''
		Athlete	Medals
Year			
2004	0	PHELPS, Michael	8
        1	THORPE, Ian	4
...	...	...	...
2008	60	MALLET, Gregory	1
        61	ZHANG, Lin	1
121 rows × 2 columns
'''
men0408.reset_index()

'''

    Year	level_1	Athlete	Medals
0	2004	0	PHELPS, Michael	8
1	2004	1	THORPE, Ian	4
...	...	...	...	...
119	2008	60	MALLET, Gregory	1
120	2008	61	ZHANG, Lin	1
121 rows × 4 columns
'''
# 최종적으로 기존의 컬럼 중 한개를 지우기

men0408.reset_index().drop(columns = ['level_1'])

'''
	Year	Athlete	Medals
0	2004	PHELPS, Michael	8
1	2004	THORPE, Ian	4
...	...	...	...
120	2008	ZHANG, Lin	1
121 rows × 3 columns
'''

# 하지만 inplace True나 오버라이트가 안되었기에 딱히 저장은 되지 않는다.


## Adding / Concatenating Rows (Part2)

men2004.head()

'''
    Athlete	Medals
0	PHELPS, Michael	8
1	THORPE, Ian	4
2	SCHOEMAN, Roland	3
3	PEIRSOL, Aaron	3
4	CROCKER, Ian	3
'''
men2008.head()

'''

    Athlete	Medals
0	PHELPS, Michael	8
1	LOCHTE, Ryan	4
2	BERNARD, Alain	3
3	SULLIVAN, Eamon	3
4	LAUTERSTEIN, Andrew	3
'''
# 컬럼명 변경
men2004.columns = ['Name', 'Medals']
men2004

'''
    Name	Medals
0	PHELPS, Michael	8
1	THORPE, Ian	4
...	...	...
57	MAGNINI, Filippo	1
58	ZWERING, Klaas-Erik	1
59 rows × 2 columns
'''
# 새 컬럼및 값 추가
# 새 컬럼 추가
# 새 컬럼 값 추가
men2004['Success'] = 'Yes'
men2004

'''
    Name	Medals	Success
0	PHELPS, Michael	8	Yes
1	THORPE, Ian	4	Yes
...	...	...	...
57	MAGNINI, Filippo	1	Yes
58	ZWERING, Klaas-Erik	1	Yes
59 rows × 3 columns
'''
# names에 주어지는 값은 컬럼값에 입력된다. 순서대로.
# 한개만 입력되면 첫번째 컬럼값인 한개만 변경된다.
pd.concat([men2004, men2008], keys = [2004, 2008], names = ['Year'])
# labels은 컬럼값이나 마찬가지다. 거기다가 axis =1이니 반드시 컬럼이고
# 그것을 drop 하는 것이다.

men2004.drop(labels = ['Success'], axis = 1, inplace = True)
men2004

'''
    Name	Medals
0	PHELPS, Michael	8
1	THORPE, Ian	4
...	...	...
57	MAGNINI, Filippo	1
58	ZWERING, Klaas-Erik	1
59 rows × 2 columns
'''
# men 2008의 컬럼 값을 men2004의 컬럼값과 동일하게 한다. 라는 의미다.
# 다만, 각 컬럼의 갯수는 일치해야 활용 되는 것으로 알고있다.
men2008.columns = men2004.columns
men2008.head()

'''
    Name	Medals
0	PHELPS, Michael	8
1	LOCHTE, Ryan	4
2	BERNARD, Alain	3
3	SULLIVAN, Eamon	3
4	LAUTERSTEIN, Andrew	3
'''

# 기존의 Athlete, Medals 컬럼 명이 Name, Medals로 변경되었다.
pd.concat([men2004, men2008], keys = [2004,2008], names = ['Year'])

'''
	Name	Medals
Year			
2004	0	PHELPS, Michael	8
1	THORPE, Ian	4
...	...	...	...
2008	60	MALLET, Gregory	1
61	ZHANG, Lin	1
121 rows × 2 columns
'''

# 이제는 concat으로 합쳐주었을때, NaN같이 불일치로 인한 결측값이 생기지는 않는다.
# 둘다 재 import 해오는데, Athlete를 기준 인덱스로 잡아준다.

men2004 = pd.read_csv('men2004.csv', index_col = 'Athlete')
men2008 = pd.read_csv('men2008.csv', index_col = 'Athlete')
men2004.head()

'''
	Medals
Athlete	
PHELPS, Michael	8
THORPE, Ian	4
SCHOEMAN, Roland	3
PEIRSOL, Aaron	3
CROCKER, Ian	3
'''
# 기존에 기준인덱스로써 Athlete가 설정 되어있다.
# 이때 concat을 사용하고, ignore_index = True를 해주게되면
# 기존에 설정되어있던 부가 값들, 이를테면 기준인덱스 등에 대해서 모두 날아가게 된다.

pd.concat([men2004, men2008], ignore_index = True, keys = [2004, 2008])

'''

    Medals
0	8
1	4
...	...
119	1
120	1
121 rows × 1 columns
'''


## Arithmetic between Pandas Objects / Data Alignment

import pandas as pd
topfive_2004 = pd.read_csv('topfive_2004.csv', index_col = 'Athlete')
topfive_2008 = pd.read_csv('topfive_2008.csv', index_col = 'Athlete')
topfive_2004

'''

                Gold	Silver	Bronze
        Athlete			
PHELPS, Michael	6.0	0.0	2.0
PEIRSOL, Aaron	3.0	0.0	0.0
THORPE, Ian	2.0	1.0	1.0
KITAJIMA, Kosuke	2.0	0.0	1.0
HACKETT, Grant	1.0	2.0	0.0
'''
topfive_2008

'''
                Gold	Silver	bronze
        Athlete			
PHELPS, Michael	8.0	0.0	0.0
GREVERS, Matt	2.0	1.0	0.0
PEIRSOL, Aaron	2.0	1.0	0.0
LOCHTE, Ryan	2.0	0.0	2.0
KITAJIMA, Kosuke	2.0	0.0	1.0
'''
topfive_2004 + topfive_2008

'''
                Bronze	Gold	Silver	bronze
        Athlete				
GREVERS, Matt	NaN	NaN	NaN	NaN
HACKETT, Grant	NaN	NaN	NaN	NaN
KITAJIMA, Kosuke	NaN	4.0	0.0	NaN
LOCHTE, Ryan	NaN	NaN	NaN	NaN
PEIRSOL, Aaron	NaN	5.0	1.0	NaN
PHELPS, Michael	NaN	14.0	0.0	NaN
THORPE, Ian	NaN	NaN	NaN	NaN
'''

# 이렇듯, 연산은 일종의 concat과 같은 기능을 하는 것으로 보인다.
# 그렇기에 서로의 데이터프레임에 겹치는 내용이 많이 없을 수록 결측값이 많이 생긴다.

# 결측치에 대한 팁****

# 결측치는 기존의 topfive_2004에서 가지고 있던 것들이 +연산 이후에 결측값으로써 없어지는 경우가 있다.
# 어느 한쪽에만 있는값인 경우에 그렇다.
# 연산하고자 하는 모든 데이터프레임에 값이 있어야 비로소 연산이되고 값이 출력된다.
# 따라서, 두 데이터 프레임 모두에만 값이 있는 경우가 6개다.
# 모든 데이터 프레임에 해당 행 인덱스의 내용이 없는 경우에 결측값이 생겼다.
# 이것을 방지 하기 위하여 사용하는 것이 add다.

topfive_2004.add(topfive_2008)

'''
            Bronze	Gold	Silver	bronze
        Athlete				
GREVERS, Matt	NaN	NaN	NaN	NaN
HACKETT, Grant	NaN	NaN	NaN	NaN
KITAJIMA, Kosuke	NaN	4.0	0.0	NaN
LOCHTE, Ryan	NaN	NaN	NaN	NaN
PEIRSOL, Aaron	NaN	5.0	1.0	NaN
PHELPS, Michael	NaN	14.0	0.0	NaN
THORPE, Ian	NaN	NaN	NaN	NaN
'''

# 여기까진 똑같다.
# 컬럼명 변경

topfive_2008.rename(columns = {'bronze':'Bronze'}, inplace = True)
# fill_value는 NaN 즉, 결측값을 대신하여 넣어주는 값이다.
topfive_2004.add(topfive_2008, fill_value = 0)

'''

                Gold	Silver	Bronze
        Athlete			
GREVERS, Matt	2.0	1.0	0.0
HACKETT, Grant	1.0	2.0	0.0
KITAJIMA, Kosuke	4.0	0.0	2.0
LOCHTE, Ryan	2.0	0.0	2.0
PEIRSOL, Aaron	5.0	1.0	0.0
PHELPS, Michael	14.0	0.0	2.0
THORPE, Ian	2.0	1.0	1.0
'''
# 여기서는 sub로써 뺄셈을 해주는 것을
# 전년도와 올해를 비교하여 성장을 나타내주는 수치로 표현해주기도 했다.

topfive_2004.sub(topfive_2008, fill_value = 0)

'''
                Gold	Silver	Bronze
         Athlete			
GREVERS, Matt	-2.0	-1.0	0.0
HACKETT, Grant	1.0	2.0	0.0
KITAJIMA, Kosuke	0.0	0.0	0.0
LOCHTE, Ryan	-2.0	0.0	-2.0
PEIRSOL, Aaron	1.0	-1.0	0.0
PHELPS, Michael	-2.0	0.0	2.0
THORPE, Ian	2.0	1.0	1.0
'''


## Outer Join
- outer join은 합집합 개념이다.

import pandas as pd

men2004 = pd.read_csv('men2004.csv')
men2008 = pd.read_csv('men2008.csv')
men2004.head()

'''
    Athlete	Medals
0	PHELPS, Michael	8
1	THORPE, Ian	4
2	SCHOEMAN, Roland	3
3	PEIRSOL, Aaron	3
4	CROCKER, Ian	3
'''
men2008.head()

'''

    Athlete	Medals
0	PHELPS, Michael	8
1	LOCHTE, Ryan	4
2	BERNARD, Alain	3
3	SULLIVAN, Eamon	3
4	LAUTERSTEIN, Andrew	3
'''
men2008.shape

# (62, 2)
len(men2004) + len(men2008)
# 121
# 여기서 men2008은 right 에 해당 하는 값을 넣어준 것이다. 
# outer join에 있어서 자동적으로 men2004는 left 측면이 되는 것이기 때문이다.
# right 측면은 join하길 원하는 부분이다.

# 결과적으로 outer join은 단 하나의 값이라도 어느 하나에 속하게 되면 join된다. or 조건이라고 보면 된다.
men2004.merge(men2008, how = 'outer', on = 'Athlete')

'''

    Athlete	Medals_x	Medals_y
0	PHELPS, Michael	8.0	8.0
1	THORPE, Ian	4.0	NaN
2	SCHOEMAN, Roland	3.0	NaN
3	PEIRSOL, Aaron	3.0	3.0
4	CROCKER, Ian	3.0	1.0
...	...	...	...
100	LAGUNOV, Evgeniy	NaN	1.0
101	BERENS, Ricky	NaN	1.0
102	LURZ, Thomas	NaN	1.0
103	MALLET, Gregory	NaN	1.0
104	ZHANG, Lin	NaN	1.0
105 rows × 3 columns
'''
# suffixes 매개변수를 통해서 Medals_x, Medals_y의 값을 변경해 줄 수 있다.
# on 매개변수는 '라벨 인덱스'라고는 하는데, 정확한 사용 기능은 잘 모르겠다.
men2004.merge(men2008, how = 'outer', on = 'Athlete', suffixes =['_2004', '_2008'])

'''

    Athlete	Medals_2004	Medals_2008
0	PHELPS, Michael	8.0	8.0
1	THORPE, Ian	4.0	NaN
2	SCHOEMAN, Roland	3.0	NaN
3	PEIRSOL, Aaron	3.0	3.0
4	CROCKER, Ian	3.0	1.0
...	...	...	...
100	LAGUNOV, Evgeniy	NaN	1.0
101	BERENS, Ricky	NaN	1.0
102	LURZ, Thomas	NaN	1.0
103	MALLET, Gregory	NaN	1.0
104	ZHANG, Lin	NaN	1.0
105 rows × 3 columns
'''

# 재미있는 결과로는 suffixes 값에 있어서 _2004, _2008로 입력해주었는데
# 각각 고유로 가지고 있던 컬럼 명+ suffixes 값으로 출력 되었다.
# indicator 매개변수를 통해서 merge의 결과값이 어디로 부터 비롯되었는지 확인할 수 있다.

men2004.merge(men2008, how = 'outer', on = 'Athlete', suffixes=['_2004', '_2008'], indicator = True)

'''

    Athlete	Medals_2004	Medals_2008	_merge
0	PHELPS, Michael	8.0	8.0	both
1	THORPE, Ian	4.0	NaN	left_only
2	SCHOEMAN, Roland	3.0	NaN	left_only
3	PEIRSOL, Aaron	3.0	3.0	both
4	CROCKER, Ian	3.0	1.0	both
...	...	...	...	...
100	LAGUNOV, Evgeniy	NaN	1.0	right_only
101	BERENS, Ricky	NaN	1.0	right_only
102	LURZ, Thomas	NaN	1.0	right_only
103	MALLET, Gregory	NaN	1.0	right_only
104	ZHANG, Lin	NaN	1.0	right_only
105 rows × 4 columns
'''
men0408 = men2004.merge(men2008, how = 'outer', on = 'Athlete', suffixes=['_2004', '_2008'], indicator=True)
men0408._merge.value_counts()

'''
right_only    46
left_only     43
both          16
Name: _merge, dtype: int64
'''

# outer join 해줄때, 왼쪽은 2004년도, 오른쪽은 2008년도의 메달 수상 기록이 있었다.
# 즉, right_only는 2008년 수상자를 의미하고
# left_only는 2004년 수상자를 의미하고
# both는 두 해에 모두 수상한 기록을 의미한다.


## Inner Join
- inner join은 교집합 개념이다.

men2004.merge(men2008, how = 'inner', on = 'Athlete', suffixes= ['_2004', '_2008'], indicator= True)

'''
    Athlete	Medals_2004	Medals_2008	_merge
0	PHELPS, Michael	8	8	both
1	PEIRSOL, Aaron	3	3	both
2	CROCKER, Ian	3	1	both
3	KITAJIMA, Kosuke	3	3	both
4	HANSEN, Brendan	3	1	both
5	HACKETT, Grant	3	2	both
6	LEZAK, Jason	2	3	both
7	KELLER, Klete	2	1	both
8	LOCHTE, Ryan	2	4	both
9	VENDT, Erik	1	1	both
10	VANDERKAAY, Peter	1	2	both
11	CSEH, Laszlo	1	3	both
12	DAVIES, David	1	1	both
13	DUBOSCQ, Hugues	1	2	both
14	GANGLOFF, Mark	1	1	both
15	JENSEN, Larsen	1	1	both
'''

# 결국, outer join의 마지막에
# men0408._merge.value_counts()
# 를 실행해주었을때를 보면, both가 16회였다.
# 이처럼 both로 함께 되어있는 것만 출력 되는게 inner join이다.


## Outer Join without Intersection
- 교집합을 제외한 합집합

import pandas as pd

men2004 = pd.read_csv('men2004.csv')
men2008 = pd.read_csv('men2008.csv')
men0408 = men2004.merge(men2008, how = 'outer', on = 'Athlete', suffixes= ('_2004', '_2008'), indicator = True)
# 이 값은 합집합의 변수다.
# 따라서, 이제 합집합 뿐만 아닌, 합집합 안의 교집합을 제거해준다.
men0408
# 교집합을 제거하기 위한 필터링 작업
men0408._merge != 'both'

'''
0      False
1       True
2       True
3      False
4      False
       ...  
100     True
101     True
102     True
103     True
104     True
Name: _merge, Length: 105, dtype: bool
'''
# 교집합 제거를 위한 필터링 적용

men0408.loc[men0408._merge != 'both']

'''
    Athlete	Medals_2004	Medals_2008	_merge
1	THORPE, Ian	4.0	NaN	left_only
2	SCHOEMAN, Roland	3.0	NaN	left_only
7	VAN DEN HOOGENBAND, Pieter	3.0	NaN	left_only
9	MORITA, Tomomi	2.0	NaN	left_only
11	ROGAN, Markus	2.0	NaN	left_only
...	...	...	...	...
100	LAGUNOV, Evgeniy	NaN	1.0	right_only
101	BERENS, Ricky	NaN	1.0	right_only
102	LURZ, Thomas	NaN	1.0	right_only
103	MALLET, Gregory	NaN	1.0	right_only
104	ZHANG, Lin	NaN	1.0	right_only
89 rows × 4 columns
'''


## Left Join without Intersection
- 오직 왼쪽의 벤다이어그램만.
- 왼쪽의 벤다이어그램 중에서도 교집합 부분을 제외하고 순수 왼쪽 벤다이어그램이 가지고 있는 값만.

men0408 = men2004.merge(men2008, how = 'outer', on = 'Athlete', suffixes=('_2004', '_2008'), indicator = True)

men0408.head()

'''
    Athlete	Medals_2004	Medals_2008	_merge
0	PHELPS, Michael	8.0	8.0	both
1	THORPE, Ian	4.0	NaN	left_only
2	SCHOEMAN, Roland	3.0	NaN	left_only
3	PEIRSOL, Aaron	3.0	3.0	both
4	CROCKER, Ian	3.0	1.0	both
'''
men0408.loc[men0408._merge == 'left_only']

'''
    Athlete	Medals_2004	Medals_2008	_merge
1	THORPE, Ian	4.0	NaN	left_only
2	SCHOEMAN, Roland	3.0	NaN	left_only
7	VAN DEN HOOGENBAND, Pieter	3.0	NaN	left_only
9	MORITA, Tomomi	2.0	NaN	left_only
11	ROGAN, Markus	2.0	NaN	left_only
...
'''

# 밑에도 값이 주르륵 있지만, 마지막에 00rows * 00 뭐 그런 안내가 없다.
# 그럴 경우 일일이 세면 시간도 문제지만, 정확도의 문제가 생길 수 있다.
# 그것을 방지해주기 위해서

men0408[men0408._merge == 'left_only'].shape

# (43, 4)

# 이렇게 해주면 rows는 43개, 즉, 43개의 값을 가졌다는 것을 알 수 있고
# columns 는 4임을 알 수 있다.


## Right Join without Intersection

# 내가 풀어본 문제.
men0408 = men2004.merge(men2008, how = 'outer', on = 'Athlete', suffixes = ['_2004', '_2008'], indicator = True)
test = men2004.merge(men2008, how = 'right', suffixes=['_2004', '_2008'], indicator= True)
right_join = test.loc[test._merge != 'both']
right_join.shape

# (55, 3)

# 결과적으로 46이 나와야하는데, 왜 55일까.
# 그래도 내꺼는 출력해보면 모두 right_only로 나오는데 말이다.
# 답안 코드

men0408 = men2004.merge(men2008, how = 'outer', on = 'Athlete',suffixes= ['_2004', '_2008'], indicator= True)

# 만약에 결과값이 다르다면 생각해볼 수 있는 단서는 사실 1가지 뿐이다.
# on을 나는 써주지 않았다. on 지정이 결과값에 미치는 영향이 있을 것같다.

# 추측이 맞는것 같다. on을 써주지 않았던 샘플 변수였던 test는 on을 안붙여 줬기에
# medal이라고 통틀어서 나온다. 몇년도 메달, 몇년도 메달이 아니라.
check = men0408.loc[men0408._merge == 'right_only']

'''
    Athlete	Medals_2004	Medals_2008	_merge
59	BERNARD, Alain	NaN	3.0	right_only
60	SULLIVAN, Eamon	NaN	3.0	right_only
61	LAUTERSTEIN, Andrew	NaN	3.0	right_only
62	GREVERS, Matt	NaN	3.0	right_only
63	RICKARD, Brenton	NaN	2.0	right_only
64	LEVEAUX, Amaury	NaN	2.0	right_only
...
'''
check.shape
# (46, 4)
# 결과값에 있어서 내가 원하던 결과 값이다.


## Left Join

# 내코드
# 이번엔 맞는 것 같다.

test = men2004.merge(men2008, how = 'left', on = 'Athlete', suffixes=['_2004', '_2008'], indicator=True)

'''
    Athlete	Medals_2004	Medals_2008	_merge
0	PHELPS, Michael	8	8.0	both
1	THORPE, Ian	4	NaN	left_only
2	SCHOEMAN, Roland	3	NaN	left_only
3	PEIRSOL, Aaron	3	3.0	both
4	CROCKER, Ian	3	1.0	both
'''
# on을 해주어서 이젠 맞게 온것 같다.
test.loc[test._merge == 'left_only']

'''
    Athlete	Medals_2004	Medals_2008	_merge
1	THORPE, Ian	4	NaN	left_only
2	SCHOEMAN, Roland	3	NaN	left_only
7	VAN DEN HOOGENBAND, Pieter	3	NaN	left_only
9	MORITA, Tomomi	2	NaN	left_only
'''
test.loc[test._merge == 'left_only'].shape

# (43, 4)
# 아니다. 결과적으로 순수한 왼쪽 벤다이어그램 값으로만 결과를 만들었다. 교집합을 제외한 수로.
# 다시해보자.
test.shape
# (59, 4)
# 음.. 사실상 처음에 merge시켜줄때 left해준것만으로도 끝이나 다름없다.


## Right join

# 내 코드
men2004.merge(men2008, how = 'right', on = 'Athlete', suffixes = ['_2004', '_2008'], indicator = True)

# 사실상 이걸로 끝이다.
# 답안 코드

men2004.merge(men2008, how = 'right', on = 'Athlete', suffixes=['_2004', '_2008'], indicator=True)
# 벤다이어그램 A와 B의 위치를 전환하여 표현

men2008.merge(men2004, how = 'left', on = 'Athlete', suffixes=['_2008', '_2004'], indicator=True)


## Joining on different Column Labels & Indexes

import pandas as pd

men2004 = pd.read_csv('men2004.csv')
men2008 = pd.read_csv('men2008.csv')
men2008.head()

'''
    Athlete	Medals
0	PHELPS, Michael	8
1	LOCHTE, Ryan	4
2	BERNARD, Alain	3
3	SULLIVAN, Eamon	3
4	LAUTERSTEIN, Andrew	3
'''
men2004.columns = ['Name', 'Medals']
men2004.head()

'''
    Name	Medals
0	PHELPS, Michael	8
1	THORPE, Ian	4
2	SCHOEMAN, Roland	3
3	PEIRSOL, Aaron	3
4	CROCKER, Ian	3
'''
men2004.merge(men2008, how = 'outer', on = 'Athlete', suffixes= ['_2004', '_2008'], indicator=True)

# KeyError가 난다.
# men2004의 컬럼명을 변경해주었기에 men2008의 'Athlete'와 맞지 않는다.
# merge를 할때 on을 설정해놓으면, 둘의 컬럼명, 컬럼수가 반드시 일치해야지 진행이 된다.
# 즉, on을 조작해주면 굳이 컬럼명, 컬럼수가 일치할 필요는 없다는 의미다.
# 만약 위의 경우처럼 컬럼명, 컬럼 수가 다를 경우엔
# merge를 해줄 기준값을 설정해주어야 한다. 왼쪽과 오른쪽 각각에 말이다.

men0408 = men2004.merge(men2008, how = 'outer', left_on = 'Name', right_on = 'Athlete', suffixes=['_2004', '_2008'], indicator=True)

'''
    Name	Medals_2004	Athlete	Medals_2008	_merge
0	PHELPS, Michael	8.0	PHELPS, Michael	8.0	both
1	THORPE, Ian	4.0	NaN	NaN	left_only
2	SCHOEMAN, Roland	3.0	NaN	NaN	left_only
3	PEIRSOL, Aaron	3.0	PEIRSOL, Aaron	3.0	both
4	CROCKER, Ian	3.0	CROCKER, Ian	1.0	both
'''

# 각각 컬럼명이 다른 것을 merge해 줌으로 인해서 결측값이 중간중간에 많이 생긴다.
# 결측값을 없애주기 위해서 fillna()를 사용해준다.
# 결측값 채워넣기
# 결측값을 다른 값으로 채워넣기

men0408.Name.fillna(men0408.Athlete, inplace=True)

'''
0       PHELPS, Michael
1           THORPE, Ian
2      SCHOEMAN, Roland
3        PEIRSOL, Aaron
4          CROCKER, Ian
             ...       
100    LAGUNOV, Evgeniy
101       BERENS, Ricky
102        LURZ, Thomas
103     MALLET, Gregory
104          ZHANG, Lin
Name: Name, Length: 105, dtype: object
'''

# fillna 메서드에서는 간단하게
# "결측값"자리에 무엇을 입력해줄래? 라고 묻는것이고
# 여기서는 '그 자리에 men0408.Athlete'를 넣을래. 라고 표현해준것이다.
men0408.head()

'''
    Name	Medals_2004	Athlete	Medals_2008	_merge
0	PHELPS, Michael	8.0	PHELPS, Michael	8.0	both
1	THORPE, Ian	4.0	NaN	NaN	left_only
2	SCHOEMAN, Roland	3.0	NaN	NaN	left_only
3	PEIRSOL, Aaron	3.0	PEIRSOL, Aaron	3.0	both
4	CROCKER, Ian	3.0	CROCKER, Ian	1.0	both
'''
# 이제 결측값을 대신하여  Athlete 값도 채워주었으니, 무의미한 컬럼을 지워주자.
men0408.drop(['Athlete', '_merge'], axis = 1, inplace = True)

'''
    Name	Medals_2004	Medals_2008
0	PHELPS, Michael	8.0	8.0
1	THORPE, Ian	4.0	NaN
2	SCHOEMAN, Roland	3.0	NaN
3	PEIRSOL, Aaron	3.0	3.0
4	CROCKER, Ian	3.0	1.0
...	...	...	...
100	LAGUNOV, Evgeniy	NaN	1.0
101	BERENS, Ricky	NaN	1.0
102	LURZ, Thomas	NaN	1.0
103	MALLET, Gregory	NaN	1.0
104	ZHANG, Lin	NaN	1.0
105 rows × 3 columns
'''
men2008

'''
    Athlete	Medals
0	PHELPS, Michael	8
1	LOCHTE, Ryan	4
2	BERNARD, Alain	3
3	SULLIVAN, Eamon	3
4	LAUTERSTEIN, Andrew	3
...	...	...
57	LAGUNOV, Evgeniy	1
58	BERENS, Ricky	1
59	LURZ, Thomas	1
60	MALLET, Gregory	1
61	ZHANG, Lin	1
62 rows × 2 columns
'''
men2008.set_index('Athlete', inplace = True)
men2008.head()

'''
        Medals
    Athlete	
PHELPS, Michael	8
LOCHTE, Ryan	4
BERNARD, Alain	3
SULLIVAN, Eamon	3
LAUTERSTEIN, Andrew	3
'''
men2004.merge(men2008, how = 'outer', left_on = 'Name', right_on = 'Athlete', 
              suffixes=['_2004', '_2008'], indicator= True)

'''
    Name	Medals_2004	Medals_2008	_merge
0	PHELPS, Michael	8.0	8.0	both
1	THORPE, Ian	4.0	NaN	left_only
2	SCHOEMAN, Roland	3.0	NaN	left_only
3	PEIRSOL, Aaron	3.0	3.0	both
4	CROCKER, Ian	3.0	1.0	both
...	...	...	...	...
100	NaN	NaN	1.0	right_only
101	NaN	NaN	1.0	right_only
102	NaN	NaN	1.0	right_only
103	NaN	NaN	1.0	right_only
104	NaN	NaN	1.0	right_only
105 rows × 4 columns

1

'''
men2004.merge(men2008, how = 'outer', left_on = 'Name', right_index = True ,
             suffixes= ['_2004', '_2008'], indicator= True)


## Joining on many Columns

import pandas as pd
men2004_det = pd.read_csv("men2004_det.csv")
men2008_det = pd.read_csv('men2008_det.csv')

men2004_det.head(10)

'''
    Athlete	Medal	Count
0	BOVELL, George	Bronze	1
1	BREMBILLA, Emiliano	Bronze	1
2	CAPPELLAZZO, Federico	Bronze	1
3	CERCATO, Simone	Bronze	1
4	CONRAD, Lars	Silver	1
5	CROCKER, Ian	Bronze	1
6	CROCKER, Ian	Gold	1
7	CROCKER, Ian	Silver	1
8	CSEH, Laszlo	Bronze	1
9	DAVIES, David	Bronze	1
'''
men2008_det.head(10)

'''
    Athlete	Medal	Count
0	ADRIAN, Nathan	Gold	1
1	BERENS, Ricky	Gold	1
2	BERNARD, Alain	Bronze	1
3	BERNARD, Alain	Gold	1
4	BERNARD, Alain	Silver	1
5	BOUSQUET, Frederick	Silver	1
6	BRITS, Grant	Bronze	1
7	BRODIE, Leith	Bronze	2
8	CALLUS, Ashley	Bronze	1
9	CAVIC, Milorad	Silver	1
'''
men2004_det.loc[men2004_det.Athlete == 'PHELPS, Michael']

'''

    Athlete	Medal	Count
50	PHELPS, Michael	Bronze	2
51	PHELPS, Michael	Gold	6
'''
men2008_det.loc[men2008_det.Athlete == 'PHELPS, Michael']

'''
    Athlete	Medal	Count
54	PHELPS, Michael	Gold	8
'''
men0408 = men2004_det.merge(men2008_det, how = 'outer', on = 'Athlete', suffixes=['_2004', '_2008'])

'''
    Athlete	Medal_2004	Count_2004	Medal_2008	Count_2008
0	BOVELL, George	Bronze	1.0	NaN	NaN
1	BREMBILLA, Emiliano	Bronze	1.0	NaN	NaN
2	CAPPELLAZZO, Federico	Bronze	1.0	NaN	NaN
3	CERCATO, Simone	Bronze	1.0	NaN	NaN
4	CONRAD, Lars	Silver	1.0	NaN	NaN
...	...	...	...	...	...
137	VYATCHANIN, Arkady	NaN	NaN	Bronze	2.0
138	WALTERS, David	NaN	NaN	Gold	1.0
139	WEBER-GALE, Garrett	NaN	NaN	Gold	2.0
140	WILDMAN-TOBRINER, Ben	NaN	NaN	Gold	1.0
141	ZHANG, Lin	NaN	NaN	Silver	1.0
142 rows × 5 columns
'''
men0408.loc[men0408.Athlete == 'PHELPS, Michael']

'''
    Athlete	Medal_2004	Count_2004	Medal_2008	Count_2008
59	PHELPS, Michael	Bronze	2.0	Gold	8.0
60	PHELPS, Michael	Gold	6.0	Gold	8.0
'''


## pd.merge and join()

import pandas as pd

men2004 = pd.read_csv('men2004.csv', index_col = 'Athlete')
men2008 = pd.read_csv('men2008.csv', index_col = 'Athlete')

men2004.head()

'''

        Medals
    Athlete	
PHELPS, Michael	8
THORPE, Ian	4
SCHOEMAN, Roland	3
PEIRSOL, Aaron	3
CROCKER, Ian	3
'''
men2008.head()

'''
            Medals
    Athlete	
PHELPS, Michael	8
LOCHTE, Ryan	4
BERNARD, Alain	3
SULLIVAN, Eamon	3
LAUTERSTEIN, Andrew	3
'''
men2004.merge(men2008, how = 'outer', on = 'Athlete', suffixes= ['_2004', '_2008'], indicator=True)

'''
	Medals_2004	Medals_2008	_merge
Athlete			
PHELPS, Michael	8.0	8.0	both
THORPE, Ian	4.0	NaN	left_only
SCHOEMAN, Roland	3.0	NaN	left_only
PEIRSOL, Aaron	3.0	3.0	both
CROCKER, Ian	3.0	1.0	both
...	...	...	...
LAGUNOV, Evgeniy	NaN	1.0	right_only
BERENS, Ricky	NaN	1.0	right_only
LURZ, Thomas	NaN	1.0	right_only
MALLET, Gregory	NaN	1.0	right_only
ZHANG, Lin	NaN	1.0	right_only
105 rows × 3 columns
'''
pd.merge(men2004, men2008, how = 'outer', on = 'Athlete', suffixes= ['_2004', '_2008'], indicator= True)

'''
	Medals_2004	Medals_2008	_merge
Athlete			
PHELPS, Michael	8.0	8.0	both
THORPE, Ian	4.0	NaN	left_only
SCHOEMAN, Roland	3.0	NaN	left_only
PEIRSOL, Aaron	3.0	3.0	both
CROCKER, Ian	3.0	1.0	both
...	...	...	...
LAGUNOV, Evgeniy	NaN	1.0	right_only
BERENS, Ricky	NaN	1.0	right_only
LURZ, Thomas	NaN	1.0	right_only
MALLET, Gregory	NaN	1.0	right_only
ZHANG, Lin	NaN	1.0	right_only
105 rows × 3 columns
'''
men2004.join(men2008, how = 'outer', lsuffix= '_2004', rsuffix='_2008')

'''
        Medals_2004	Medals_2008
    Athlete		
ADRIAN, Nathan	NaN	1.0
BERENS, Ricky	NaN	1.0
BERNARD, Alain	NaN	3.0
BOUSQUET, Frederick	NaN	1.0
BOVELL, George	1.0	NaN
...	...	...
WOODWARD, Gabe	1.0	NaN
YAMAMOTO, Takashi	2.0	NaN
ZASTROW, Mitja	1.0	NaN
ZHANG, Lin	NaN	1.0
ZWERING, Klaas-Erik	1.0	NaN
105 rows × 2 columns
'''
300x250