달나라 노트

Python Pandas : DataFrame.join 본문

Python/Python Pandas

Python Pandas : DataFrame.join

CosmosProject 2020. 11. 6. 19:09
728x90
반응형

 

 

DataFrame.join

DataFrame의 join은 merger와 비슷한 기능을 제공합니다.

먼저 test용 DataFrame을 생성합니다.

import pandas as pd
dict_a = {
    'id1': [1, 2, 3, 4, 5],
    'name': ['a', 'b', 'c', 'd', 'e'],
    'price': [10, 20, 30, 40, 50]
}

dict_b = {
    'id2': [1, 2, 3, 4],
    'name': ['a', 'b', 'z', 'z'],
    'price': [10, 20, 100, 100]
}

df_a = pd.DataFrame(dict_a)
df_b = pd.DataFrame(dict_b)

print(df_a)
print(type(df_a))

print(df_b)
print(type(df_b))
 
- Output 1
   id1 name  price
0    1    a     10
1    2    b     20
2    3    c     30
3    4    d     40
4    5    e     50
<class 'pandas.core.frame.DataFrame'>

   id2 name  price
0    1    a     10
1    2    b     20
2    3    z    100
3    4    z    100
<class 'pandas.core.frame.DataFrame'>




join은 아래처럼 사용할 수 있습니다.

 

df_left.join(df_right -> df_left인 DataFrame에 df_right을 join합니다. (기본적으로 left join의 형태로 진행됩니다.)

 

lsuffix='_l' -> 중복된 컬럼이 있을 경우 df_left에 존재하는 중복컬럼에 붙일 suffix를 지정합니다.

 

rsuffix='_r' -> 중복된 컬럼이 있을 경우 df_right에 존재하는 중복컬럼에 붙일 suffix를 지정합니다.

import pandas as pd
df_new = df_left.join(df_right, lsuffix='_l', rsuffix='_r')

 

 

아래 코드는 join의 예시입니다.

 

df_test = df_a.join(df_b, lsuffix='_l', rsuffix='_r')

print(df_test)
print(type(df_test))
 
- Output
   id1 name_l  price_l  id2 name_r  price_r
0    1      a       10  1.0      a     10.0
1    2      b       20  2.0      b     20.0
2    3      c       30  3.0      z    100.0
3    4      d       40  4.0      z    100.0
4    5      e       50  NaN    NaN      NaN
<class 'pandas.core.frame.DataFrame'>

 

원본 df_a, df_b입니다. 이걸 참고해서 join이 어떻게 진행되는지 직접 보면 좋습니다.

- df_a
   id1 name  price
0    1    a     10
1    2    b     20
2    3    c     30
3    4    d     40
4    5    e     50

- df_b
   id2 name  price
0    1    a     10
1    2    b     20
2    3    z    100
3    4    z    100

 

 

근데 한 가지 이상한 점은 merge method를 사용할 때에는 두 DataFrame을 병합할 때 사용할 column을 명시했는데 join에서는 그렇지 않았다는 것입니다.

 

그 이유는 join은 기본적으로 오른쪽 DataFrame의 index를 인식하여 왼쪽 DataFrame에 존재하는 동일한 index를 가진 행끼리 병합을 하게됩니다.

(여기서 주의할 점은 join을 할 때 DataFrame에 중복되는 index가 존재하면 Error를 발생시킵니다.)

 

join의 또다른 특징은 df_left와 df_right에 있는 모든 개개의 컬럼이 결과물로 반환된다는 것입니다.

 

또한 중복된 컬럼에 대해서는 컬럼 명에 지정한 접미어(suffix)가 붙었음을 알 수 있죠.

 

 

 

 

 

위 예시의 결과를 merge로 비슷하게 반환하려면 아래와 같습니다.

(df_a, df_b의 id1, id2 컬럼의 이름을 모두 id로 통일했다고 가정합시다.)

 

위에서 설명했던 것 처럼 merge에서는 DataFrame 병합 시에 병합의 기준이 될 key를 'left_on=['id'], right_on=['id']'의 형태로 명시했습니다.

 

또 한 가지의 차이는 merge에선 기준이 된 key column은 중복되어 나오지 않고 1개만 출력됩니다.

 

그래서 아래 결과를 보면 id라는 컬럼이 id_l, id_r 등으로 2개 출력되지 않고 id라는 딱 하나의 컬럼만 결과물에 있음을 알 수 있죠.

 

또한 merge에서도 중복된 컬럼을 위해 suffix를 지정 가능한데 list의 형태로 전달해야 합니다.

 

그리서 해당 리스트의 첫 번째 요소인 '_l'은 왼쪽 DataFrame(df_a)의 중복컬럼에 접미어로 붙었음을 알 수 있고, 두 번째 요소인 '_r'은 오른쪽 DataFrame(df_b)의 중복 컬럼에 접미어로 붙었음을 알 수 있습니다.

df_test = pd.DataFrame.merge(df_a, df_b, how='left', left_on=['id'], right_on=['id'], suffixes=['_l', '_r'])

print(df_test)
print(type(df_test))
 
- Output
   id name_l  price_l name_r  price_r
0   1      a       10      a     10.0
1   2      b       20      b     20.0
2   3      c       30      z    100.0
3   4      d       40      z    100.0
4   5      e       50    NaN      NaN
<class 'pandas.core.frame.DataFrame'>




첫 설명에서 join은 두 DataFrame의 index를 병합 시에 사용되는 기준 key로 사용한다고 했는데 만약 index가 아니라 특정 컬럼의 데이터를 기준 key로 사용하고싶으면 어떻게 해야할까요?

 

아래 예시처럼 on 인자를 사용하면 됩니다.

 

on=['id1']의 의미는 왼쪽 DataFrame의 id1컬럼 데이터와 오른쪽 DataFrame의 index값이 동일한 행끼리 join하겠다는 의미입니다.

 

따라서 id1 컬럼에있는 1이 df_b의 index = 1인 행과 연결된 것을 알 수 있죠.

df_test = df_a.join(df_b, on=['id1'], lsuffix='_l', rsuffix='_r')

print(df_test)
print(type(df_test))
 
- Output
   id1 name_l  price_l  id2 name_r  price_r
0    1      a       10  2.0      b     20.0
1    2      b       20  3.0      z    100.0
2    3      c       30  4.0      z    100.0
3    4      d       40  NaN    NaN      NaN
4    5      e       50  NaN    NaN      NaN
<class 'pandas.core.frame.DataFrame'>


원본 df_a, df_b입니다. 이걸 참고해서 join이 어떻게 진행되는지 직접 보면 좋습니다.

- df_a
   id1 name  price
0    1    a     10
1    2    b     20
2    3    c     30
3    4    d     40
4    5    e     50

- df_b
   id2 name  price
0    1    a     10
1    2    b     20
2    3    z    100
3    4    z    100



 

 

 

또한 merge에서와 마찬가지로 join의 대상이 될 DataFrame은 original DataFrame뿐만 아니라 아래 예시에 적힌 3가지 예시에서처럼 loc나 set_index등을 이용하여 DataFrame의 일부를 추출하여 사용할 수도 있습니다.

 

tip.set_index는 어떤 컬럼에 존재하는 값들은 index값으로 설정하는 기능을 가집니다.

 

즉, 아래 예시의 첫 번째 df_test에서 df_b 대신에 'df_b.set_index('id2')'를 넣어줌으로써 df_b의 id2 컬럼의 데이터를 index로 보낸 것입니다.

 

그리고 join은 이 index로 변경된 id2컬럼을 join시에 기준으로 사용할 것이고,

그 결과 DataFrame에서 df_b의 index는 표시되지 않음으로 결국 id2 컬럼은 반환되지 않았음을 알 수 있습니다.

df_test = df_a.join(df_b.set_index('id2'), on=['id1'], lsuffix='_l', rsuffix='_r')
print(df_test)

df_test = df_a.loc[:, ['id1']].join(df_b, on=['id1'], lsuffix='_l', rsuffix='_r')
print(df_test)

df_test = df_a.loc[:, ['id1']].join(df_b.set_index('id2'), on=['id1'], lsuffix='_l', rsuffix='_r')
print(df_test)
 
- Output
   id1 name_l  price_l name_r  price_r
0    1      a       10      a     10.0
1    2      b       20      b     20.0
2    3      c       30      z    100.0
3    4      d       40      z    100.0
4    5      e       50    NaN      NaN

   id1  id2 name  price
0    1  2.0    b   20.0
1    2  3.0    z  100.0
2    3  4.0    z  100.0
3    4  NaN  NaN    NaN
4    5  NaN  NaN    NaN

   id1 name  price
0    1    a   10.0
1    2    b   20.0
2    3    z  100.0
3    4    z  100.0
4    5  NaN    NaN



- tip : df_b.set_index('id2')의 결과
    name  price
id2            
1      a     10
2      b     20
3      z    100
4      z    100

 

 

 

 

 

 

728x90
반응형
Comments