sort_values 메서드는 값을 기준으로 레이블을 정렬하는 메서드입니다.
by : 정렬 기준이될 레이블입니다.
axis : {0 : index / 1: columns} 정렬할 레이블입니다. 0이면 행, 1이면 열을 기준으로 정렬합니다.
inplace : 원본을 대체할지 여부입니다. True일 경우 원본을 대체하게 됩니다.
kind : 알고리즘 모드 입니다. 모드는 총 4종으로 quicksort, mergesort,
heapsort, stable이 있는데,
속도와 효율성의 차이를 갖습니다. 기본적으로 quicksort이며, 자세한건 numpy doc에서 확인 가능합니다.
na_position : {first / last} Na값의 위치입니다. 기본값은 last로 정렬시 맨 뒤에 위치합니다.
ignore_index : 인덱스의 무시 여부입니다. True일 경우 인덱스의 순서와 상관없이 0,1,2,... 로 정해집니다.
key : 이 인수를 통해 정렬방식으로 함수를 사용할 수 있습니다. lamba의 사용이 가능합니다.
먼저 np.NaN이 포함된 간단한 5x3짜리 데이터를 만들어보겠습니다.
na = np.NaN
data = [[-3,'A',17],
[na,'D',31],
[ 7,'D',-8],
[15,'Z', 3],
[ 0, na,-7]]
col = ['col1','col2','col3']
row = ['row1','row2','row3','row4','row5']
df = pd.DataFrame(data = data, index = row, columns= col)
print(df)
>>
col1 col2 col3
row1 -3.0 A 17
row2 NaN D 31
row3 7.0 D -8
row4 15.0 Z 3
row5 0.0 NaN -7
정렬의 기준이 되는 by에는 레이블명이 되는 str이 올수도 있고, 레이블명들의 list가 올 수 있습니다.
list형태가 올 경우, 첫 값부터 정렬합니다.
print(df.sort_values(by='col3'))
#col3을 기준으로 오름차순 정렬된 것을 확인할 수 있습니다.
col1 col2 col3
row3 7.0 D -8
row5 0.0 NaN -7
row4 15.0 Z 3
row1 -3.0 A 17
row2 NaN D 31
print(df.sort_values(by=['col2','col3']))
# col2 기준으로 정렬 후 같은값인 'D'에 대해서는
# col3 기준으로 정렬된 것을 확인 할 수 있습니다
col1 col2 col3
row1 -3.0 A 17
row3 7.0 D -8
row2 NaN D 31
row4 15.0 Z 3
row5 0.0 NaN -7
axis인수의 사용
axis인수를 사용하여 어떤축을 기준으로 정렬할지 설정이 가능합니다.
단, 문자와 숫자의 혼용시 오류가 발생합니다. ※ Na는 무시됩니다.
열 기준 col3으로 오름차순 정렬
print(df.sort_values(by='col3',axis=0))
col1 col2 col3
row3 7.0 D -8
row5 0.0 NaN -7
row4 15.0 Z 3
row1 -3.0 A 17
row2 NaN D 31
행 기준 row1의 오름차순 정렬. 문자와 숫자의 혼용으로 오류가 발생합니다.
print(df.sort_values(by='row1',axis=1))
>>
오류 발생
행 기준 row5의 오름차순 정렬. 문자와 NaN의 혼용이기 때문에 정상적으로 정렬 됩니다.
print(df.sort_values(by='row5',axis=1))
col3 col1 col2
row1 17 -3.0 A
row2 31 NaN D
row3 -8 7.0 D
row4 3 15.0 Z
row5 -7 0.0 NaN
ascending인수의 사용
ascending인수를 이용하여 오름차순과 내림차순을 설정할 수 있습니다.
기본값은 True로 오름차순입니다. 내림차순의 경우 False로 아래와 같습니다.
print(df.sort_values(by='col3',ascending=False))
col1 col2 col3
# col3 기준으로 내림차순정렬이 된 것을 알 수 있습니다.
row2 NaN D 31
row1 -3.0 A 17
row4 15.0 Z 3
row5 0.0 NaN -7
row3 7.0 D -8
na_position인수의 사용
na_position인수를 이용하여 결측값의 위치를 지정할 수 있습니다.
결측값이 맨 뒤(기본값)
print(df.sort_values(by='col1',na_position='last'))
col1 col2 col3
row1 -3.0 A 17
row5 0.0 NaN -7
row3 7.0 D -8
row4 15.0 Z 3
row2 NaN D 31
결측값이 맨 앞
print(df.sort_values(by='col1',na_position='first'))
col1 col2 col3
row2 NaN D 31
row1 -3.0 A 17
row5 0.0 NaN -7
row3 7.0 D -8
row4 15.0 Z 3
ignore_index인수의 사용
ignore_index인수를 사용하여 인덱스를 미사용 할 수 있습니다. 어떤식으로 정렬 되더라도
인덱스는 0, 1, 2, 3, ... 순서로 표시됩니다.
print(df.sort_values(by='col3',ignore_index=True))
col1 col2 col3
0 7.0 D -8
1 0.0 NaN -7
2 15.0 Z 3
3 -3.0 A 17
4 NaN D 31
key인수의 사용
key인수를 사용하여 정렬에 함수를 이용할 수 있습니다
print(df.sort_values(by='col2',key=lambda col: col.str.lower()))
col1 col2 col3
row1 -3.0 A 17
row2 NaN D 31
row3 7.0 D -8
row4 15.0 Z 3
row5 0.0 NaN -7
inplcae 인수의 사용
inplace 인수를 사용해서 원본을 대체할지의 여부를 설정할 수 있습니다.
df.sort_values(by='col3',inplace=True)
print(df) #그냥 df를 출력함으로써 원본의 대체 여부가 확인 가능합니다.
col1 col2 col3
row3 7.0 D -8
row5 0.0 NaN -7
row4 15.0 Z 3
row1 -3.0 A 17
row2 NaN D 31
axis : {0 : index / 1: columns} 정렬할 레이블입니다. 0이면 행, 1이면 열을 기준으로 정렬합니다.
level : multi index의 경우 정렬을 진행할 level입니다.
ascending : 오름차순으로할지 여부 입니다. 기본은 True로 오름차순입니다.
inplace : 원본을 대체할지 여부입니다. True일 경우 원본을 대체하게 됩니다.
kind : 알고리즘 모드 입니다. 모드는 총 4종으로 quicksort, mergesort,heapsort, stable이 있는데,
속도와 효율성의 차이를 갖습니다. 기본적으로 quicksort이며, 자세한건 numpy doc에서 확인 가능합니다.
na_position : {first / last} Na값의 위치입니다. 기본값은 last로 정렬시 맨 뒤에 위치합니다.
sort_remaining : multi index의 경우 다른 레벨에 대해서도 정렬을할지 여부입니다. True로 할 경우
한 레벨에 대한 정렬이 완료되면, 다른 레벨도 정렬합니다.
ignore_index : 인덱스의 무시 여부입니다. True일 경우 인덱스의 순서와 상관없이 0,1,2,... 로 정해집니다.
level의 지정
level을 지정하므로써 해당 level에서의 정렬이 가능합니다.
level이 0인 경우 row기준으로 정렬되는것을 확인 할 수 있습니다.
print(df.sort_index(axis=0, level=0))
col4 col1 col2
row1 val1 1.0 2.0 3
val2 4.0 NaN 6
row2 val2 19.0 20.0 21
val5 16.0 17.0 18
row3 val1 NaN 11.0 12
val2 13.0 14.0 15
val3 7.0 8.0 9
level이 1인 경우 val기준으로 정렬되는것을 확인 할 수 있습니다.
print(df.sort_index(axis=0, level=1))
col4 col1 col2
row1 val1 1.0 2.0 3
row3 val1 NaN 11.0 12
row1 val2 4.0 NaN 6
row2 val2 19.0 20.0 21
row3 val2 13.0 14.0 15
val3 7.0 8.0 9
row2 val5 16.0 17.0 18
level별 ascending의 병용
level과 ascending의 값을 list형태로 입력하므로써, 각 level에 다른 정렬방식의 사용이 가능합니다.
level이 1인 val이 내림차순 정렬되고, level이 0인 row가 오름차순 정렬된것을 확인 할 수 있습니다.
print(df.sort_index(axis=0, level=[1,0],ascending=[False,True]))
col4 col1 col2
row2 val5 16.0 17.0 18
row3 val3 7.0 8.0 9
row1 val2 4.0 NaN 6
row2 val2 19.0 20.0 21
row3 val2 13.0 14.0 15
row1 val1 1.0 2.0 3
row3 val1 NaN 11.0 12
sort_remaining 인수의 사용
multi index에서 sort_remaining인수를 True로 할 경우 level별로 순차적으로 정렬이 진행됩니다.
만약 level을 따로 지정했다면, 해당 level부터 정렬한 후 나머지 level을 순차적으로 정렬합니다.
row정렬 후 val의 정렬까지 완료된 것을 확인할 수 있습니다.
print(df.sort_index(axis=0, sort_remaining=True))#기본적으로 sort_remaining은 True가 기본값이다
col4 col1 col2
row1 val1 1.0 2.0 3
val2 4.0 NaN 6
row2 val2 19.0 20.0 21
val5 16.0 17.0 18
row3 val1 NaN 11.0 12
val2 13.0 14.0 15
val3 7.0 8.0 9
nlargest메서드와 nsmallest메서드는 데이터를 오름차순/내림차순 정렬 후, 위에서 n개의 행을 출력하는 메서들입니다.
사실상 df.sort_values(columns, ascending=True/False).head(n)와 사용방식이 완전히 동일합니다.
n : 정렬 후 출력할 행의 수 입니다.
columns : 정렬의 기준이 될 열 입니다.
keep :{first, last, all} 동일한 값일경우 어느 행을 출력할지 정합니다. first면 위부터, last면 아래부터, all이면 모두 출력합니다.
col = ['col1','col2','col3']
row = ['row3','row5','row1','row4','row2']
data = [[ 1, 21, 7],
[ 2, 33, 3],
[ 2, 7,97],
[ 4, 56,31],
[ 5, 18, 5]]
df = pd.DataFrame(data=data, index=row, columns=col)
print(df)
>>
col1 col2 col3
row3 1 21 7
row5 2 33 3
row1 2 7 97
row4 4 56 31
row2 5 18 5
keep 인수의 사용
keep인수를 통해 중복일경우의 출력할 행을 지정할 수 있습니다.
처음 발생한 값부터 출력(위쪽값 출력)
print(df.nlargest(n=3, columns='col1',keep='first'))
#중복된 값은 첫번째 부터 출력한다
col4 col1 col2
row2 val2 19.0 20.0 21
val5 16.0 17.0 18
row3 val2 13.0 14.0 15
print(df.nlargest(n=3, columns='col1',keep='last'))#컬럼1에서 가장 큰값 3개를 출력한다, 중복된 값은 마지막 값을 출력한다
col4 col1 col2
row2 val2 19.0 20.0 21
val5 16.0 17.0 18
row3 val2 13.0 14.0 15
중복값 모두 출력
print(df.nlargest(n=3,columns='col1',keep='all'))#중복된 값도 모두 출력한다
>>
col1 col2 col3
row2 5 18 5
row4 4 56 31
row5 2 33 3
row1 2 7 97
여러 열을 동시에 고려하여 정렬
여러 열을 동시에 고려하여 정렬하고자 한다면 list를 사용하면됩니다.
col1과 col3 모두에서 큰 값 기준 정렬할 경우 아래와 같습니다.
Copyprint(df.nlargest(n=3,columns=['col1','col3']))
#만약 col1값이 같다면 col3까지 비교를 한다
>>
col1 col2 col3
row2 5 18 5
row4 4 56 31
row1 2 7 97
#col1에서 중복인 row1, row5에 대해 col3의 값이 더 큰 row1이 출력
combine 메서드는 두 pandas 객체를 func함수를 이용하여 결합하는 메서드입니다.
other : 결합 할 DataFrame객체 입니다.
func : 결합에 이용할 함수 입니다.
fill_value : 결합하기전 Na의 값을 이 값으로 대체합니다.
overwrite : other에 존재하지 않는 self의 열의 값을 NaN으로 대체합니다.
먼저 np.NaN이 포함된 간단한 3x3짜리 데이터 2개를 만들어보겠습니다.
n=np.nan
col = ['col1','col2','col3']
row = ['row1','row2','row3']
data1 = [[1,3,4],
[n,8,2],
[2,6,7]]
data2 = [[7,2,3],
[2,4,2],
[3,1,5]]
df1 = pd.DataFrame(data1,row,col)
df2 = pd.DataFrame(data2,row,col)
print(df1)
print(df2)
col1 col2 col3
row1 1.0 3 4
row2 NaN 8 2
row3 2.0 6 7
col1 col2 col3
row1 7 2 3
row2 2 4 2
row3 3 1 5
기본적인 사용법
func 인수에 np.maximum을 입력하여 df1과 df2의 요소를 비교, 큰 값으로 결합하여 보겠습니다.
print(df1.combine(df2,np.maximum))
>>
col1 col2 col3
row1 7.0 3 4
row2 NaN 8 2
row3 3.0 6 7
fill_value를 이용하여 결측치 채우기
fill_value에 값을 입력하면, 결측치가 해당 값으로 채워진 후 결합이 진행됩니다.
print(df1.combine(df2,np.maximum,fill_value=9))#결측값을 9로 채운다
col1 col2 col3
row1 7.0 3 4
row2 9.0 8 2
row3 3.0 6 7
col1, row2의 값이 NaN에서 9로 변경 된후 np.maximum이 진행된 것을 확인할 수 있습니다.
overwrite 인수의 사용
overwrite인수는 other에 존재하지 않는 self의 열의 요소를 NaN으로 변경하는 메서드입니다.
먼저 이해를 돕기 위해 2x2 데이터인 df3을 만들어 보겠습니다.
col3 = ['col1','col2']
row3 = ['row1','row2']
data3 = [[1,2],
[3,4]]
df3 = pd.DataFrame(data3, row3, col3)
print(df3)
>>
col1 col2
row1 1 2
row2 3 4
overwrite가 False일 경우 존재하지 않는 열에 대해서는 기존값으로 채워집니다.
print(df1.combine(df3, np.maximum,overwrite=False))
#존재하지 않는 열에 대해서는 기존값(df1)으로 채워진다
col1 col2 col3
row1 1.0 3.0 4
row2 NaN 8.0 2
row3 NaN NaN 7
overwrite가 True일 경우 존재하지 않는 열에 대해서는 NaN으로 채워집니다.
col3의 값이 모두 NaN으로 채워진 것을 확인할 수 있습니다.
print(df1.combine(df3, np.maximum,overwrite=True))#결측값으로 채워진다
col1 col2 col3
row1 1.0 3.0 NaN
row2 NaN 8.0 NaN
row3 NaN NaN NaN
combine_first 메서드는 other의 값으로 self(df)의 NaN값을 덮어쓰는 메서드입니다.
other : self객체의 결측치를 덮어쓸 객체 입니다.
n=np.nan
col = ['col1','col2','col3']
row = ['row1','row2','row3']
data1 = [[n,n,1],
[n,n,1],
[1,1,1]]
data2 = [[2,2,2],
[2,n,2],
[2,1,2]]
df1 = pd.DataFrame(data1,row,col)
df2 = pd.DataFrame(data2,row,col)
print(df1)
print(df2)
col1 col2 col3
row1 NaN NaN 1
row2 NaN NaN 1
row3 1.0 1.0 1
col1 col2 col3
row1 2 2.0 2
row2 2 NaN 2
row3 2 1.0 2
기본적인 사용법
self객체의 NaN값을 other객체의 같은위치의 인수로 덮어쓰기 합니다.
만약 self에서 NaN인 값이 other에서도 NaN이라면 NaN을 출력합니다.
print(df1.combine_first(df2))#df1에 df2를 덮어 쒸웁니다
col1 col2 col3
row1 2.0 2.0 1
row2 2.0 NaN 1
row3 1.0 1.0 1
join 메서드는 두 객체를 인덱스 기준으로 병합하는 메서드 입니다.
other : self와 합칠 객체 입니다.
on : self의 열이나 인덱스 중에서 other의 어떤 열을 기준으로 결합할지 입니다.
즉, other의 (인덱스 기준이 아닌) 열 기준으로 결합할 때 on인수를 사용합니다.
how : {left : self기준 / right : other기준 / inner : 교집합 / outer : 합집합} 출력할 인덱스의 기준입니다.
lsuffix / rsffix : 이름이 중복되는 열이 있을 때 그 열에 추가로 붙일 접미사입니다.
lsuffix는 self의 열에 붙을 접미사고, rsuffix는 other의 열에 붙을 접미사입니다.
sort : 출력되는 데이터의 index를 사전적으로 정렬할지 여부입니다.
기본데이터 생성
df1 = pd.DataFrame({'col1':[1,2,3]},index=['row3','row2','row1'])
print(df1)
col1
row3 1
row2 2
row1 3
df2 = pd.DataFrame({'col2':[13,14]},index=['row4','row3'])
print(df2)
col2
row4 13
row3 14
df3 = pd.DataFrame({'col1':[23,24]},index=['row4','row3'])
print(df3)
col1
row4 23
row3 24
df4 = pd.DataFrame({'IDX':['A','B','C'],'col1':[1,2,3]})
print(df4)
IDX col1
0 A 1
1 B 2
2 C 3
df5 = pd.DataFrame({'IDX':['C','D'],'col2':[13,14]})
print(df5)
IDX col2
0 C 13
1 D 14
how를 통한 인덱스의 설정
how인수를 통해 인덱스의 기준을 어떤 값으로 할지 정할 수 있습니다
how=left인 경우 (기본값) df1의 인덱스를 기준으로 합니다.
print(df1.join(df2,how='left'))
col1 col2
row3 1 14.0
row2 2 NaN
row1 3 NaN
how=right인 경우 df2의 인덱스를 기준으로 합니다.
print(df1.join(df2,how='right'))
col1 col2
row4 NaN 13
row3 1.0 14
how=outer인 경우 df1와 df2의 인덱스의 합집합을 기준으로 합니다.
print(df1.join(df2,how='outer'))
col1 col2
row1 3.0 NaN
row2 2.0 NaN
row3 1.0 14.0
row4 NaN 13.0
how=inner인 경우 df1와 df2의 인덱스의 교집합을 기준으로 합니다.
print(df1.join(df2,how='inner'))
col1 col2
row3 1 14
sort 인수를 통한 인덱스의 정렬
sort인수를 True로 설정할 경우 인덱스의 값을 사전적으로 정렬 할 수 있습니다.
sort가 False 인경우(기본값)
print(df1.join(df2,how='left'))
col1 col2
row3 1 14.0
row2 2 NaN
row1 3 NaN
sort가 True 인경우 인덱스가 정렬 된 것을 확인할 수 있습니다.
print(df1.join(df2,how='left',sort=True))
col1 col2
row1 3 NaN
row2 2 NaN
row3 1 14.0
lsuffix / rsuffix 인수를 통해 중복 열 구분하df1과 df3은 col1이라는 이름이 중복된 열을 가지기 때문에, join메서드를 사용할 경우 오류가 발생하게 됩니다.
이때, lsuffix / rsuffix 인수를 입력함으로서 기존 열 이름에 접미사를 붙일 수 있습니다.
print(df1.join(df3,how='outer',lsuffix="_left",rsuffix='_right'))
col1_left col1_right
row1 3.0 NaN
row2 2.0 NaN
row3 1.0 24.0
row4 NaN 23.0
인덱스가 아닌 열 기준으로 결합하기(+ on 인수의 사용) 먼저 IDX라는 이름의 열을 갖는 두 객체를 생성해보겠습니다.
df4 = pd.DataFrame({'IDX':['A','B','C'],'col1':[1,2,3]})
print(df4)
IDX col1
0 A 1
1 B 2
2 C 3
df5 = pd.DataFrame({'IDX':['C','D'],'col2':[13,14]})
print(df5)
IDX col2
0 C 13
1 D 14
join메서드는 기본적으로 index를 기준으로 결합하기 때문에, 열 기준으로 결합하기 위해서는
set_index메서드를 활용해 열을 인덱스로 변경하여 join메서드를 사용하면 됩니다.
print(df4.set_index('IDX').join(df5.set_index('IDX')))
IDX
A 1 NaN
B 2 NaN
C 3 13.0
하지만 위와 같이 진행 할 경우 기존 인덱스가 열 값으로 변경됩니다.
이를 방지하고 순수하게 열 기준으로 병합하려면 on 인수를 사용하면 됩니다.
print(df4.join(df5.set_index('IDX'),on='IDX'))
IDX col1 col2
0 A 1 NaN
1 B 2 NaN
2 C 3 13.0
merge메서드는 두 객체를 병합하는 메서드입니다. join과 비슷하지만 더 세부적인 설정이 가능한 메서드로,
인덱스-열 기준 병합도 가능하며, indicator인수를 통한 병합정보확인, validate를 통한 병합방식 확인등이 가능합니다.
left.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
right: left와 함께 병합할 객체입니다.
how : 병합시 기준이 될 인덱스를 정하는 방식입니다. left는 기존객체, right는 병합할 객체, inner은 두 객체의 인덱스의 교집합, outer은 두 객체의 인덱스의 합집합, cross는 행렬곱 입니다.
on : 열 기준 병합시 기준으로할 열의 이름이 양측이 동일하다면, on인수에 입력함으로써 기준 열을 정할 수 있습니다.
left_on / right_on : 열기준 병합 시 기준으로 할 열의 양측 이름이 다르다면, 각각 어떤 열을 기준으로 할지 정해줍니다.
열의 이름을 입력하면 됩니다.
left_index / right_index : 인덱스 기준 병합 시 True로 하면 해당 객체의 인덱스가 병합 기준이됩니다.
※ 즉 left_on을 입력하고 right_index를 True로 한다면 열-인덱스 기준 병합도 가능합니다.
sort : 병합 후 인덱스의 사전적 정렬 여부입니다. join메서드와 기능이 동일하므로 참고 바랍니다.
suffixes : 병합할 객체들간 이름이 중복되는 열이 있다면, 해당 열에 붙일 접미사를 정합니다.
기본적으로 join메서드의 lsuffix / rsuffix와 기능이 동일하지만, suffixes인수는 튜플로 두 값을
한번에 입력한다는 차이가 있습니다.
copy : 사본을 생성할지 여부입니다.
indicator : True로 할경우 병합이 완료된 객체에 추가로 열을 하나 생성하여 병합 정보를 출력합니다.
validate : {'1:1' / '1:m' / 'm:1' / 'm:m'} 병합 방식에 맞는지 확인할 수 있습니다. 만약 validate에 입력한 병합방식과, 실제 병합 방식이 다를경우 오류가 발생됩니다.
예를들어, validate="1:m"으로 입력하였는데, 실제로 m:1 병합방식일 경우 오류가 발생됩니다.
열 기준으로 병합 (left_on / right_on)
left_on / right_on에 열 이름을 입력하므로서 열 기준으로 병합이 가능합니다.
먼저 객체 2개를 만들어 보겠습니다.
df1 = pd.DataFrame({'IDX1':['a','b','c','a'],'VAL':[1,2,3,4]})
print(df1)
IDX1 VAL
0 a 1
1 b 2
2 c 3
3 a 4
df2 = pd.DataFrame({'IDX2':['a','c','d'],'VAL':[5,6,7]})
print(df2)
IDX2 VAL
0 a 5
1 c 6
2 d 7
df1에서는 IDX1을, df2에서는 IDX2를 기준으로 하여 두 객체를 병합하겠습니다.
IDX1과 IDX2의 값을 매칭하여 병합된 후 이름이 같은 VAL열에 대해서는 _x와 _y가 붙었습니다.
print(df1.merge(df2, left_on='IDX1',right_on='IDX2'))
IDX1 VAL_x IDX2 VAL_y
0 a 1 a 5
1 c 3 c 6
2 a 4 a 5
suffixes를 통한 동명인 열 구분
suffixes에 ('_left', '_right')를 입력하므로써 열 이름에 _left, _right를 붙일 수 있습니다.
print(df1.merge(df2, left_on='IDX1',right_on='IDX2',suffixes = ('_left','_right')))
IDX1 VAL_left IDX2 VAL_right
0 a 1 a 5
1 c 3 c 6
2 a 4 a 5
인덱스 기준으로 병합(left_index / right_index)
left_index / right_index를 통해 인덱스 기준으로 두 객체를 병합할 수 있습니다.
먼저 병합할 두 객체를 만들어보겠습니다.
df3 = pd.DataFrame({'VAL1':[1,2,3]},index=['row1','row2','row3'])
print(df3)
>>
VAL1
row1 1
row2 2
row3 3
df4 = pd.DataFrame({'VAL2':[4,5,6]},index=['row2','row3','row4'])
print(df4)
>>
VAL2
row2 4
row3 5
row4 6
left_index와 right_index를 True로 입력하여 두 객체 모두 인덱스를 기준으로 병합할 수 있습니다.
print(df3.merge(df4, left_index=True,right_index=True))
VAL1 VAL2
row2 2 4
row3 3 5
열과 인덱스를 혼합하여 병합하기
left_on / right_on 과 left_index / right_index를 이용하여 양쪽의 기준을 설정해줌으로서, 인덱스와 열의 혼합 병합도 가능합니다.
예시를 위해서 새 객체 두개를 만들어보겠습니다.
df5는 인덱스를, df6은 열을 기준으로 하겠습니다.
df5 = pd.DataFrame({'VAL1':[1,2,3]},index=['row1','row2','row3'])
print(df5)
>>
VAL1
row1 1
row2 2
row3 3
df6 = pd.DataFrame({'IDX':['row2','row3','row4'],'VAL2':[4,5,6]})
print(df6)
>>
IDX VAL2
0 row2 4
1 row3 5
2 row4 6
이제 left_index는 True로하여 인덱스를 기준으로하고 right_on은 IDX로 하여 열 기준으로 병합하겠습니다.
print(df5.merge(df6, left_index=True,right_on='IDX'))
VAL1 IDX VAL2
0 2 row2 4
1 3 row3 5
how 인수의 사용
how인수를 사용하여 병합된 객체의 인덱스의 기준을 정할 수 있습니다.
먼저 예시에 이용될 두 객체를 만들어 보겠습니다.
df7 = pd.DataFrame({'IDX':['a','b','c','a'],'VAL':[1,2,3,4]})
print(df7)
>>
IDX VAL
0 a 1
1 b 2
2 c 3
3 a 4
Copydf8 = pd.DataFrame({'IDX':['a','c','d'],'VAL':[5,6,7]})
print(df8)
>>
IDX VAL
0 a 5
1 c 6
2 d 7
how=left인 경우 왼쪽 객체의 인덱스를 기준으로 합니다.
print(df7.merge(df8,how='left',on='IDX'))
IDX VAL_x VAL_y
0 a 1 5.0
1 b 2 NaN
2 c 3 6.0
3 a 4 5.0
how=right인 경우 오른쪽 객체의 인덱스를 기준으로 합니다.
print(df7.merge(df8,how='right',on='IDX'))
IDX VAL_x VAL_y
0 a 1.0 5
1 a 4.0 5
2 c 3.0 6
3 d NaN 7
how=inner인 경우 양쪽 객체 모두가 공통으로 갖는 인덱스를 기준으로 합니다.(교집합)
print(df7.merge(df8,how='inner',on='IDX'))
>>
IDX VAL_x VAL_y
0 a 1 5
1 a 4 5
2 c 3 6
how=outer인 경우 양쪽 객체의 인덱스 모두를 기준으로 합니다.(합집합)
print(df7.merge(df8,how='outer',on='IDX'))
>>
IDX VAL_x VAL_y
0 a 1.0 5.0
1 a 4.0 5.0
2 b 2.0 NaN
3 c 3.0 6.0
4 d NaN 7.0
※cross에 대해서는 뒤에 후술하겠습니다.
indicator인수를 통한 병합 정보 출력
indicator인수를 True로 할 경우 마지막 열에 _merge열을 추가하여 병합 정보를 출력합니다.
print(df7.merge(df8,how='outer',on='IDX',indicator=True))
>>
IDX VAL_x VAL_y _merge
0 a 1.0 5.0 both
1 a 4.0 5.0 both
2 b 2.0 NaN left_only
3 c 3.0 6.0 both
4 d NaN 7.0 right_only
validate를 통한 병합방식 검증
validate인수에 값을 입력하여 해당 병합방식이 맞는지 검증이 가능합니다. 병합 방식이 다를경우 오류를 출력합니다.
1:m인지 검증
print(df7.merge(df8,how='outer',on='IDX',validate='1:m'))
>>
오류발생
pandas.errors.MergeError: Merge keys arenot uniquein left dataset;not a one-to-many merge
m:1인지 검증. 병합 방식이 m:1이 맞기 때문에 결과값을 출력합니다.
print(df7.merge(df8,how='outer',on='IDX',validate='m:1'))
>>
IDX VAL_x VAL_y
0 a 1.0 5.0
1 a 4.0 5.0
2 b 2.0 NaN
3 c 3.0 6.0
4 d NaN 7.0
how인수에 cross를 적용하는 경우
how인수중 cross는 행렬의 곱집합을 의미합니다. 단순히 말하면 행렬의 모든 경우의수를 출력합니다.
예시를 위해 두 객체를 생성해보겠습니다.
df9 = pd.DataFrame({'IDX1':['a','b']})
print(df9)
>>
IDX1
0 a
1 b
df10 = pd.DataFrame({'IDX2':['c','d']})
print(df10)
>>
IDX2
0 c
1 d
이제 how인수에 cross를 입력하므로써 두 객체의 행렬곱을 출력하겠습니다.
print(df9.merge(df10,how='cross'))
>>
IDX1 IDX2
0 a c
1 a d
2 b c
3 b d
align메서드는 두 객체를 특정 기준들에 맞추어 정렬하는 메서드입니다.
두개의 데이터를 튜플 형태로 반환한다는것을 반드시 명심하시기 바랍니다.
인수들에 따라 다양한 구현이 가능하므로 아래 사용법을 참고 바랍니다.
self.align(other, join='outer', axis=None, level=None, copy=True, fill_value=None, method=None, limit=None, fill_axis=0, broadcast_axis=None)
other : self와 함께 정렬할 객체 입니다.
join : {inner / left / right / outer} 정렬 기준이 될 인덱스 입니다. inner이면 교집합, left면 self의 인덱스, right면 other의 인덱스, outer이면 합집합으로 인덱스를 사용합니다.
axis : {0 : index / 1 : columns} 정렬할 레이블입니다. 기본값으로 두 축 모두 정렬합니다.
level : multi index의 경우 실행할 수준(level)을 설정합니다.
copy : 사본을 생성할지의 여부입니다.
fill_value : 결측치를 어떤 값으로 채울지의 여부입니다. 기존 객체에 포함된 결측치의 경우는 바뀌지 않습니다.
method : {ffill / bfill} 결측치를 어떻게 채울지 여부입니다. ffill의 경우 위의값과 동일하게, bfill의 경우 아래 값과 동일하게 채웁니다.
limit : 결측치를 몇개나 채울지 여부입니다. limit에 설정된 갯수만큼만 결측치를 변경합니다.
fill_axis : {0 : index / 1 : columns} method와 limit를 가로로 적용할지 세로로 적용할지 여부입니다.
broadcast_axis : {0 : index / 1 : columns} 어느 축을 기준으로 브로드캐스트할지 여부입니다.
브로드캐스트란 서로 차원이 다른 두 객체에 대해서 저차원 데이터의 차원을 고차원 데이터에 맞추는 과정입니다.
기본 사용법
먼저 일부 레이블을 공유하는 3x3짜리 데이터 2개를 만들어보겠습니다.
전체적으로 보면 아래와 같습니다.(빨강이 df1, 파랑이df2, 녹색이 레이블이 겹치는구간)
| index | col1 | col2 | col3 | col4 |
|---|---|---|---|---|
| row1 | 1 | 2 | 3 | x |
| row2 | 5 | 6 | 7 | x |
| row3 | 9 | 10 | 11 | 12 |
| row4 | x | 14 | NA | 16 |
| row5 | x | 18 | 19 | 20 |
편의를 위해 겹치는 부분의 값을 동일하게 했습니다
두개의 데이터를 튜플 형태로 반환하기 때문에, 달라도 상관없습니다.
n=np.NaN
col1 = ['col1','col2','col3']
row1 = ['row1','row2','row3']
data1 = [[1,2,3],[5,6,7],[9,n,11]]
col2 = ['col2','col3','col4']
row2 = ['row3','row4','row5']
data2 = [[10,11,12],[14,n,16],[18,19,20]]
df1 = pd.DataFrame(data1,row1,col1)
df2 = pd.DataFrame(data2,row2,col2)
print(df1)
>>
col1 col2 col3
row1 1 2.0 3
row2 5 6.0 7
row3 9 NaN 11
print(df2)
>>
col2 col3 col4
row3 10 11.0 12
row4 14 NaN 16
row5 18 19.0 20
join 인수의 사용을 통한 레이블 설정
join 인수를 이용해 {outer : 합집합 / left : df1기준 / right : df2기준 / inner : 교집합} 인 index로 출력합니다.
두개의 데이터를 튜플 형태로 반환하기 때문에 리스트 슬라이싱으로 따로 print를 진행해보겠습니다.
outer로 출력시 레이블이 df1과 df2 모두의 합집합으로 사용되고 있는것을 알 수 있습니다.
print(df1.align(df2,join='outer')[0])
print(df1.align(df2,join='outer')[1])
col1 col2 col3 col4
row1 1.0 2.0 3.0 NaN
row2 5.0 6.0 7.0 NaN
row3 9.0 NaN 11.0 NaN
row4 NaN NaN NaN NaN
row5 NaN NaN NaN NaN
col1 col2 col3 col4
row1 NaN NaN NaN NaN
row2 NaN NaN NaN NaN
row3 NaN 10.0 11.0 12.0
row4 NaN 14.0 NaN 16.0
row5 NaN 18.0 19.0 20.0
left로 출력시 df1의 레이블만 사용되는 것을 알 수 있습니다.
print(df1.align(df2,join='left')[0])
print(df1.align(df2,join='left')[1])
col1 col2 col3
row1 1 2.0 3
row2 5 6.0 7
row3 9 NaN 11
col1 col2 col3
row1 NaN NaN NaN
row2 NaN NaN NaN
row3 NaN 10.0 11.0
right로 출력시 df2의 레이블만 사용되는 것을 알 수 있습니다.
print(df1.align(df2,join='right')[0])
print(df1.align(df2,join='right')[1])
col2 col3 col4
row3 NaN 11.0 NaN
row4 NaN NaN NaN
row5 NaN NaN NaN
col2 col3 col4
row3 10 11.0 12
row4 14 NaN 16
row5 18 19.0 20
inner로 출력시 레이블이 df1과 df2 모두의 교집합으로 사용되고 있는것을 알 수 있습니다.
print(df1.align(df2,join='inner')[0])
print(df1.align(df2,join='inner')[1])
col2 col3
row3 NaN 11
col2 col3
row3 10 11.0
axis 인수의 사용을 통한 정렬 축 설정
axis인수를 통해 정렬을 진행 할 축을 정할 수 있습니다. 기본적으로 두축 모두 입니다.
df1에 대해서만 inner로 출력하여 확인해보겠습니다.
axis를 0으로 하였을 경우 행 기준 inner인 row3만 정렬되었습니다.
print(df1.align(df2,join='inner',axis=1)[0])
col2 col3
row1 2.0 3
row2 6.0 7
row3 NaN 11
fill_value를 사용한 결측치 입력
fill_value를 사용해서 결측치를 원하는 값으로 변경이 가능합니다.
단, 기존 객체에 입력되어있던 결측치의 경우 변경되지 않습니다.
print(df1.align(df2,join='outer',fill_value='X')[0])
print(df1.align(df2,join='outer',fill_value='X')[1])
col1 col2 col3 col4
row1 1 2.0 3 X
row2 5 6.0 7 X
row3 9 NaN 11 X
row4 X X X X
row5 X X X X
col1 col2 col3 col4
row1 X X X X
row2 X X X X
row3 X 10 11.0 12
row4 X 14 NaN 16
row5 X 18 19.0 20
method / limit인수를 사용한 결측치 보정
method인수는 {ffill / bfill}를 이용해 위쪽 또는 아래쪽 값으로 결측치 보정이 가능합니다.
limit인수의 경우는 method인수를 통해 결측치 보정할 때, 몇개의 값을 보정할지 설정합니다.
ffill로 입력 시 결측값을 바로 위의 값과 동일하게, bfill로 입력 시 결측값을 바로 아래 값과 동일하게 변경 된것을 확인할 수 있습니다.
print(df1.align(df2,join='outer',method='ffill')[0])
print(df1.align(df2,join='outer',method='bfill')[1])
>>
col1 col2 col3 col4
row1 1.0 2.0 3.0 NaN
row2 5.0 6.0 7.0 NaN
row3 9.0 6.0 11.0 NaN
row4 9.0 6.0 11.0 NaN
row5 9.0 6.0 11.0 NaN
col1 col2 col3 col4
row1 NaN 10.0 11.0 12.0
row2 NaN 10.0 11.0 12.0
row3 NaN 10.0 11.0 12.0
row4 NaN 14.0 19.0 16.0
row5 NaN 18.0 19.0 20.0
limit 설정시 각 레이블에 대해서 아래와 같이 설정한 갯수만 변경 됩니다.
print(df1.align(df2,join='outer',method='bfill',limit=1)[1])
>>
col1 col2 col3 col4
row1 NaN NaN NaN NaN
row2 NaN 10.0 11.0 12.0
row3 NaN 10.0 11.0 12.0
row4 NaN 14.0 19.0 16.0
row5 NaN 18.0 19.0 20.0
fill_axis 인수의 사용
fill_axis는 method및 limit를 어느축 기준으로 실행할지 여부입니다. 즉, 가로로 할지 세로로할지 여부입니다.
print(df1.align(df2,join='outer',method='ffill',fill_axis=0)[0])
print(df1.align(df2,join='outer',method='ffill',fill_axis=1)[0])
>>
col1 col2 col3 col4
row1 1.0 2.0 3.0 NaN
row2 5.0 6.0 7.0 NaN
row3 9.0 6.0 11.0 NaN
row4 9.0 6.0 11.0 NaN
row5 9.0 6.0 11.0 NaN
col1 col2 col3 col4
row1 1.0 2.0 3.0 3.0
row2 5.0 6.0 7.0 7.0
row3 9.0 9.0 11.0 11.0
row4 NaN NaN NaN NaN
row5 NaN NaN NaN NaN
update메서드는 DataFrame의 열을 other객체의 동일한 열의 값으로 덮어씌우는 메서드입니다.
반환값 없이 원본이 변경됩니다.
self.update(other, join='left', overwrite=True, filter_func=None, errors='ignore')
other : self에 덮어씌울 객체 입니다.
join : {left} 기준이 될 인덱스 입니다. left만 선택 가능하므로 무시해도됩니다.
overwrite : {True / False} 덮어씌울 방식입니다. True면 self의 모든 데이터에 other을 덮어씌웁니다.
False면 self에서 Na인 값에 대해서만 덮어씌우기를 진행합니다.
filter_func : 덮어씌울값을 함수로 정할 수 있습니다.
errors : {raise / ignore} raise일 경우 self와 other 모두 Na가 아닌 값이 있을경우 오류를 발생시킵니다.
df1 = pd.DataFrame({'A':[1,2,3],'B':[n,5,6]})
print(df1)
>>
A B
0 1 NaN
1 2 5.0
2 3 6.0
df2 = pd.DataFrame({'B':[24,n,26],'C':[37,38,39]})
print(df2)
>>
B C
0 24.0 37
1 NaN 38
2 26.0 39
overwrite인수로 업데이트 방식 설정
overwrite인수가 True면 df1과 df2가 이름을 공유하는 열에 대해서 df2의 값을 df1에 덮어씌웁니다.
False일 경우 df1에서 Na인 값에 대해서만 덮어씌우기를 진행합니다.
※ df2에서 Na인 값의 경우 덮어씌워지지 않습니다.
overwrite=True일 경우(기본값)
df1.update(df2,overwrite=True)
print(df1)
>>
A B # df1의 Na를 포함 덮어씌우기가 진행됨. 5의 경우 df2의 값이 Na이므로 무시
0 1 24.0
1 2 5.0
2 3 26.0
overwrite=False일 경우
df1.update(df2,overwrite=False)
print(df1)
>>
A B # df1에서 Na인 값에 대해서만 업데이트가 진행됨.
0 1 24.0
1 2 5.0
2 3 6.0
filter_func로 원하는 값만 업데이트
filter_func에 함수를 넣음으로서 원하는 값만 업데이트가 가능합니다.
6인 값에 대해서만 업데이트를 하도록 filter_func를 설정하겠습니다
df1.update(df2,filter_func=lambda x: x==6)
print(df1)
>>
A B #df1에서 6인 값에 대해서만 업데이트가 진행됨.
0 1 NaN
1 2 5.0
2 3 26.0
errors인수의 사용법
errors인수를 raise로 할 경우 df1과 df2 모두 같은 위치에 Na가 아닌 값이 있을 경우 오류를 발생시킵니다.
Copydf1.update(df2,errors='raise')
print(df1)
>>
오류발생
ValueError: Data overlaps.