Python

[Python] Dataframe 병합

,,πŸͺ¨,, 2024. 10. 17. 00:06
λ°˜μ‘ν˜•

λ°μ΄ν„°ν”„λ ˆμž„ 병합


데이터 μ „μ²˜λ¦¬ μž‘μ—…μ„ μ§„ν–‰ν•˜λ‹€λ³΄λ©΄ λ°μ΄ν„°ν”„λ ˆμž„μ„ μ—¬λŸ¬κ°œλ‘œ λ‚˜λˆ„κ³  λ˜λ‹€μ‹œ ν•˜λ‚˜λ‘œ ν•©μΉ˜λŠ” λ“±μ˜ κ²½μš°κ°€ λ°œμƒν•œλ‹€. 이번 ν¬μŠ€νŒ…μ€ μ΄λŸ¬ν•œ 경우 μ‚¬μš©ν•  수 μžˆλŠ” λ°μ΄ν„°ν”„λ ˆμž„ 병합 λ©”μ†Œλ“œμ— λŒ€ν•΄μ„œ λ‹€λ£¨μ–΄λ³΄μž.

pd.concat()


concatμ΄λΌλŠ” ν•¨μˆ˜λͺ…μ—μ„œλ„ μ•Œ 수 μžˆλ“―μ΄ concat ν•¨μˆ˜λŠ” λ°μ΄ν„°ν”„λ ˆμž„μ„ μ—°κ²°μ‹œμΌœμ£ΌλŠ” ν•¨μˆ˜μ΄λ‹€.

λ¨Όμ € 병합을 μœ„ν•œ λ°μ΄ν„°ν”„λ ˆμž„μ„ λ‘κ°œ μƒμ„±ν•΄λ³΄μž

In [5]:

import pandas as pd

df1 = pd.DataFrame({'a':['a0','a1','a2','a3'],
                   'b':['b0','b1','b2','b3'],
                   'c':['c0','c1','c2','c3']},
                  index = [0,1,2,3])

df2 = pd.DataFrame({'a':['a2','a3','a4','a5'],
                   'b':['b2','b3','b4','b5'],
                   'c':['c2','c3','c4','c5'],
                   'd':['d2','d3','d4','d5']},
                   index = [2,3,4,5])

print(df1,'\n\n', df2)
    a   b   c
0  a0  b0  c0
1  a1  b1  c1
2  a2  b2  c2
3  a3  b3  c3 

     a   b   c   d
2  a2  b2  c2  d2
3  a3  b3  c3  d3
4  a4  b4  c4  d4
5  a5  b5  c5  d5

μœ„μ˜ 두 λ°μ΄ν„°ν”„λ ˆμž„μ„ μ‚΄νŽ΄λ³΄λ©΄ ν–‰ indexλͺ…κ³Ό 컬럼λͺ…이 λ‹€λ₯΄λ‹€. μ΄λŒ€λ‘œ pd.concat() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ μ–΄λ–»κ²Œ λ˜λŠ”μ§€ μ‚΄νŽ΄λ³΄μž.

pd.concat() 에 λ“€μ–΄κ°€λŠ” μΈμžκ°’μœΌλ‘œλŠ” 리슀트λ₯Ό λ°›λŠ”λ‹€λŠ” 점을 κΈ°μ–΅ν•˜μž

pd.concat([df1, df2]) # axis=0 λ””ν΄νŠΈ

μ•„λ¬΄λŸ° μ˜΅μ…˜ 없이 ν–‰ μΈλ±μŠ€μ™€ μ—΄ μΈλ±μŠ€κ°€ μ„œλ‘œ λ‹€λ₯Έ 두 λ°μ΄ν„°ν”„λ ˆμž„μ„ λ³‘ν•©ν•˜λŠ” 경우 μœ„μ™€ 같이 λ³‘ν•©λ˜κΈ° μ „ μžμ‹ μ˜ 인덱슀λ₯Ό κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜κ³  μ—΄ μΈλ±μŠ€κ°€ λ§žμ§€ μ•ŠλŠ” 뢀뢄은 NaN κ°’μœΌλ‘œ μ±„μ›Œμ§„λ‹€.

이 λ•Œ ν–‰ 인덱슀λ₯Ό μž¬λ°°μ—΄ν•˜κΈ° μœ„ν•œ μ˜΅μ…˜μœΌλ‘œ ignore_index=Trueλ₯Ό μ§€μ •ν•  수 μžˆλ‹€.

In [13]:

result = pd.concat([df1, df2], ignore_index=True)
result

null값은 fillna λ©”μ†Œλ“œλ₯Ό 톡해 처리 κ°€λŠ₯ν•˜λ‹€.

result.fillna(0)

μ΄λ²ˆμ—λŠ” axis=1둜 μ§€μ •ν•΄μ„œ μ—΄λ°©ν–₯으둜 두 λ°μ΄ν„°ν”„λ ˆμž„μ„ λ³‘ν•©ν•΄λ³΄μž. 사싀상 λ°μ΄ν„°ν”„λ ˆμž„μ„ κ°€λ‘œλ‘œ λΆ™μ΄λŠ” κ²½μš°λŠ” 거의 μ—†κΈ° λ•Œλ¬Έμ— λ””ν΄νŠΈ 값은 ν–‰λ°©ν–₯을 κ°–λŠ”λ‹€.

pd.concat([df1, df2], axis=1)

μ—΄λ°©ν–₯으둜 axisλ₯Ό μ§€μ •ν•˜κ³  두 λ°μ΄ν„°ν”„λ ˆμž„μ„ λ³‘ν•©ν•œ κ²°κ³Ό ν–‰ μΈλ±μŠ€μ™€ μ—΄ μΈλ±μŠ€κ°€ λ§žμ§€ μ•ŠλŠ” 뢀뢄에 λŒ€ν•΄μ„œ null 값을 λ°˜ν™˜ν•œλ‹€.

λ§Œμ•½ 두 null값을 μ œμ™Έν•œ ꡐ집합을 λ§Œλ“€κ³  μ‹Άλ‹€λ©΄ join μ˜΅μ…˜μ„ inner둜 μ§€μ •ν•œλ‹€.

pd.concat([df1, df2], axis=1, join='inner')

pd.concat ν•¨μˆ˜μ˜ join μ˜΅μ…˜μ€ λ””ν΄νŠΈλ‘œ outer join을 μˆ˜ν–‰ν•œλ‹€. λ”°λΌμ„œ μœ„μ™€ 같이 null 값이 λ°˜ν™˜λ˜μ—ˆλ˜ 것이고 inner join을 μˆ˜ν–‰ν•˜λ©΄ null값을 μ œμ™Έν•œ κ΅μ§‘ν•©λ§Œμ„ λ°˜ν™˜ν•œλ‹€.

Series 데이터와 DataFrame의 병합


Pandas의 DataFrame의 Series의 집합이닀. λ”°λΌμ„œ Seriesλ₯Ό DataFrame에 λ³‘ν•©ν•˜λŠ” 것 λ˜ν•œ κ°€λŠ₯ν•œλ° 이 λ•Œ SereisλŠ” ν•˜λ‚˜μ˜ 컬럼이라고 μ΄ν•΄ν•˜λ©΄ λœλ‹€.

μ•„λž˜μ˜ μ˜ˆμ‹œλŠ” s1μ΄λΌλŠ” μ—΄ 인덱슀(컬럼λͺ…)을 κ°€μ§„ Sereis 객체λ₯Ό df1에 λ³‘ν•©ν•˜λŠ” μ˜ˆμ‹œμ΄λ‹€.

In [20]:

s1 = pd.Series(['s0', 's1', 's2', 's4'], name='s1')

pd.concat([df1, s1], axis=1) # 결과적으둜 μ»¬λŸΌμ„ λΆ™μ΄λŠ” 것이기 λ•Œλ¬Έμ— axis=1둜 μ§€μ •

Seriesκ°„μ˜ 병합


pd.concat ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄ Seriesκ°„μ˜ 병합 λ˜ν•œ κ°€λŠ₯ν•˜λ‹€.

In [27]:

s1 = pd.Series(['a0', 'b1', 'c2', 'd4'], name='s1')
s2 = pd.Series(['e0', 'f1', 'g2', 'h4'], name='s2')

print(pd.concat([s1, s2], axis=0, ignore_index=True))
print('\n\n')
print(pd.concat([s1, s2], axis=1))
0    a0
1    b1
2    c2
3    d4
4    e0
5    f1
6    g2
7    h4
dtype: object



   s1  s2
0  a0  e0
1  b1  f1
2  c2  g2
3  d4  h4

μ•žμ˜ Series의 병합에 λŒ€ν•΄ μ‚΄νŽ΄λ³΄μ•˜λ“―μ΄ 사싀상 Series의 병합은 μΆ”κ°€μ˜ κ°œλ…μ— 더 가깝닀고 λ³Ό 수 μžˆλ‹€.

pd.merge()


merge() ν•¨μˆ˜λŠ” 두 λ°μ΄ν„°ν”„λ ˆμž„μ„ λ³‘ν•©ν•˜λŠ” κΈ°λŠ₯을 μˆ˜ν–‰ν•œλ‹€λŠ” μ μ—μ„œ pd.concat()ν•¨μˆ˜μ™€ λ™μΌν•˜λ‹€.

ν•˜μ§€λ§Œ merge() ν•¨μˆ˜λŠ” λ³‘ν•©ν•˜κ³ μž ν•˜λŠ” 두 λ°μ΄ν„°ν”„λ ˆμž„μ˜ κ³ μœ κ°’(key)λ₯Ό κΈ°μ€€μœΌλ‘œ λ³‘ν•©ν•˜ λ•Œ μ‚¬μš©ν•œλ‹€λŠ” μ μ—μ„œ 차이가 μžˆλ‹€.

In [39]:

df1 = pd.DataFrame({
    'data1':range(6),
    'key':list('aabbcc')
})

df2 = pd.DataFrame({
    'data2':range(3),
    'key':list('cad')
})

print(df1, '\n\n', df2)
   data1 key
0      0   a
1      1   a
2      2   b
3      3   b
4      4   c
5      5   c 

    data2 key
0      0   c
1      1   a
2      2   d

λ¨Όμ € 두 λ°μ΄ν„°ν”„λ ˆμž„μ˜ ꡬ성뢀터 μ‚΄νŽ΄λ³΄μž df1은 6개의 행을 κ°€μ§€κ³  있고 μ€‘λ³΅λ˜λŠ” key 컬럼의 값듀을 κ°€μ§€κ³  μžˆλ‹€.

그리고 df2λŠ” 3개의 ν–‰κ³Ό κ³ μœ ν•œ key 컬럼의 값듀을 κ°€μ§€κ³  μžˆλ‹€.

pd.merge() ν•¨μˆ˜λŠ” 두 λ°μ΄ν„°ν”„λ ˆμž„μ— μ‘΄μž¬ν•˜λŠ” κ³ μœ κ°’μ„ κΈ°μ€€μœΌλ‘œ λ³‘ν•©ν•œλ‹€κ³  μ„€λͺ…ν–ˆλ‹€. 이 경우 두 λ°μ΄ν„°ν”„λ ˆμž„μ—μ„œ κ³΅ν†΅μ μœΌλ‘œ κ°€μ§€κ³  μžˆλŠ” κ³ μœ ν•œ ν‚€ 값은 key 컬럼의 값듀이 λœλ‹€.

λ¨Όμ € μ•„λ¬΄λŸ° μ˜΅μ…˜μ„ μ§€μ •ν•˜μ§€ μ•Šκ³  merge ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄λ³΄μž.

merge ν•¨μˆ˜μ˜ λ””ν΄νŠΈ μ˜΅μ…˜μ€ 곡톡 열이름을 κΈ°μ€€μœΌλ‘œ inner join을 μˆ˜ν–‰ν•œλ‹€.

merge(how='inner')

In [40]:

pd.merge(df1, df2)

μœ„μ˜ κ²°κ³Όλ₯Ό ν™•μΈν•˜λ©΄ inner join으둜 κ³΅ν†΅λœ μ—΄ 이름(key)을 κΈ°μ€€μœΌλ‘œ data2의 값듀이 μ€‘λ³΅λ˜μ„œ 합쳐지고 κ³΅ν†΅λ˜μ§€ μ•ŠλŠ” keyκ°’ d에 λŒ€ν•΄μ„  κ³΅ν†΅λ˜λŠ” 값이 μ—†μ–΄ μƒλž΅λœλ‹€.

μ΄λ²ˆμ—λŠ” merge ν•¨μˆ˜μ— outer join을 μˆ˜ν–‰ν•΄λ³΄μž

merge(how='outer')

In [41]:

pd.merge(df1, df2, on='key', how='outer')

outer join을 μˆ˜ν–‰ν•˜λ©΄ κ³΅ν†΅λ˜μ§€ μ•ŠλŠ” 값듀에 λŒ€ν•΄ NaN 값을 λ°˜ν™˜ν•œλ‹€.

merge(how='left')

In [43]:

pd.merge(df1, df2, on='key', how='left')

left join을 μˆ˜ν–‰ν•˜λ©΄ df1λ₯Ό κΈ°μ€€μœΌλ‘œ join을 μˆ˜ν–‰ν•˜μ—¬ df2에 ν•΄λ‹Ή key 값이 μ—†λŠ” 경우NaN 값을 λ°˜ν™˜ν•œλ‹€.

merge(how='right')

In [44]:

pd.merge(df1, df2, on='key', how='right')

right join을 μˆ˜ν–‰ν•˜λ©΄ left joinκ³Ό λ°˜λŒ€λ‘œ df1에 ν•΄λ‹Ή key 값이 μ—†λŠ” 경우 NaN값을 λ°˜ν™˜ν•œλ‹€.

left_on & right_on

how μ˜΅μ…˜μ„ μ΄μš©ν•΄ μ—¬λŸ¬ join을 μ΄μš©ν•  수 μžˆλŠ”λ° μΆ”κ°€μ μœΌλ‘œ left_onκ³Ό right_on μ˜΅μ…˜μ„ μ΄μš©ν•΄μ„œ μ™Όμͺ½ DF의 ν‚€κ°’κ³Ό 였λ₯Έμͺ½ DF의 킀값이 같은 것듀 끼리 m * n μ‘°ν•©μœΌλ‘œ λ°μ΄ν„°ν”„λ ˆμž„ 병합이 κ°€λŠ₯ν•˜λ‹€.

μ˜ˆμ‹œλ₯Ό 톡해 μ–΄λ–»κ²Œ λ°μ΄ν„°ν”„λ ˆμž„ 병합이 κ°€λŠ₯ν•œμ§€ μ•Œμ•„λ³΄μž

In [46]:

df1 = pd.DataFrame({
    'data1' : range(7),
    'lkey' : list('abcabca')
})

df2 = pd.DataFrame({
    'data2' : range(3),
    'rkey' : list('abd')
})

In [47]:

pd.merge(df1, df2, left_on='lkey', right_on='rkey')

μœ„ κ²°κ³Όλ₯Ό 확인해보면 두 λ°μ΄ν„°ν”„λ ˆμž„μ˜ key 값이 κ°™μ§€ μ•Šμ§€λ§Œ left_onκ³Ό right_on μ˜΅μ…˜μ„ μ΄μš©ν•΄ key 값을 μ§€μ •ν•œ 것을 확인할 수 μž‡λ‹€. μΆ”κ°€μ μœΌλ‘œ merge ν•¨μˆ˜μ˜ how μ˜΅μ…˜μ€ inner join이 λ””ν΄νŠΈμ΄κΈ° λ•Œλ¬Έμ— μœ„μ™€ 같은 κ²°κ³Όκ°€ λ°˜ν™˜λœκ²ƒμ΄λ‹€.

join()


join ν•¨μˆ˜λŠ” merge() ν•¨μˆ˜λ₯Ό 기반으둜 λ§Œλ“€μ–΄μ‘ŒμœΌλ©° μž‘λ™λ°©μ‹μ΄ λΉ„μŠ·ν•˜μ§€λ§Œ ν–‰ 인덱슀λ₯Ό κΈ°μ€€μœΌλ‘œ λ°μ΄ν„°ν”„λ ˆμž„μ„ λ³‘ν•©ν•œλ‹€λŠ” μ μ—μ„œ 차이가 μžˆλ‹€.

In [54]:

df1 = pd.DataFrame({
    'data1' : range(7),
    'lkey' : list('abcabca'),
}, index = range(7))

df2 = pd.DataFrame({
    'data2' : range(3),
    'rkey' : list('abd')
}, index = [2, 3, 4])

In [55]:

df1.join(df2)

join ν•¨μˆ˜λŠ” λ””ν΄νŠΈκ°’μœΌλ‘œ left join을 μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— μœ„μ™€ 같은 κ²°κ³Όλ₯Ό 확인할 수 μžˆλ‹€.

병합 κΈ°μ€€ μ—­μ‹œ ν–‰ 인덱슀λ₯Ό 기반으둜 병합이 μˆ˜ν–‰λ˜μ—ˆλ‹€.

λ°˜μ‘ν˜•