๐Ÿ’ฟ Data/๋ถ€ํŠธ์บ ํ”„

[TIL]3.Data Manipulation(๊ฐœ์ธ์ ์œผ๋กœ ์ž˜ ์•Œ์•„์•ผ ๋œ๋‹ค๊ณ  ๋Š๊ผˆ๋˜ ๋ถ€๋ถ„)

Jayden1116 2021. 11. 27. 12:55

๋ชฉํ‘œ

  • pandas๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ concat/mergeํ•˜๊ธฐ
  • tidy ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๊ฐœ๋… ์ดํ•ด
  • melt์™€ pivot/pivot_table ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ wide์™€ tidy ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

Pandas๋กœ ๋ฐ์ดํ„ฐ ํ•ฉ์น˜๊ธฐ


์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์˜ˆ๋กœ ๋“ค๋ฉด, ์ข…๋ชฉ๋ณ„ ๋ฐ์ดํ„ฐ์™€ ์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ค ์ข…๋ชฉ์„ ์˜๋ฏธํ•˜๋Š”์ง€ ์„ค๋ช…ํ•˜๋Š” description ๋ฐ์ดํ„ฐ๋กœ ๋‚˜๋ˆ„์–ด ์งˆ ์ˆ˜ ์žˆ๋‹ค.
ํšจ๊ณผ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ถ„์„์„ ํ•˜๊ธฐ์œ„ํ•ด์„œ๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒ์ผ์„ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์•ผํ•œ๋‹ค!!!
์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฐฉ๋ฒ• ์ค‘ 2๊ฐ€์ง€๋ฅผ ์†Œ๊ฐœํ•ด๋ณด๊ฒ ๋‹น

Concat(concatenate)

๊ฐ„๋‹จํ•˜๊ฒŒ '๋”ํ•œ๋‹ค' ํ˜น์€ '๋ถ™์ธ๋‹ค'๋ผ๋Š” ์˜๋ฏธ๋กœ ์ƒ๊ฐํ•˜๋ฉด ์ดํ•ด๊ฐ€ ํŽธํ•˜๋‹ค.
๋ฌธ์žํ˜• ๋ถ™์ด๋Š” ๋Š๋‚Œ

'๋ฌธ์ž๋ฅผ' + '๋ถ™์—ฌ์š”' == '๋ฌธ์ž๋ฅผ๋ถ™์—ฌ์š”'

๋œฌ๊ธˆ์—†์ง€๋งŒ ๋ฌธ์žํ˜•์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

  • ๋ถ™์ด๊ธฐ : tostring, join
  • ๋ถ„๋ฆฌํ•˜๊ธฐ : split

Dataframe๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์—ด์ด๋‚˜ ํ–‰์„ ๊ธฐ์ค€์œผ๋กœ ๋ถ™์ผ ์ˆ˜ ์žˆ๋‹ค.

  • index์™€ column์ด ๊ฐ™์€ ๊ฒฝ์šฐ


  • index์™€ column์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ


์˜ˆ์‹œ!

import pandas as pd
x = pd.DataFrame([['AX','AY'],['BX','BY']], index = ['A','B'], columns = ['X','Y'])
y = pd.DataFrame([['AX','AZ'],['CX','CZ']], index = ['A','C'], columns = ['X','Z'])

์ผ ๋•Œ,

pd.concat([x,y]) # ๊ธฐ๋ณธ์ ์œผ๋กœ ํ–‰ row(axis=0)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•ฉ์ณ์ง€๊ฒŒ ๋˜์–ด์žˆ๋‹ค.

X Y Z
A AX AY NaN
B BX BY NaN
A AX NaN AZ
C CX NaN CZ

pd.concat([x,y], axis=1) # ์—ด cloumn(axis=1)์„ ๊ธฐ์ค€์œผ๋กœ ํ•ฉ์นœ๋‹ค.

X Y X Z
A AX AY AX AZ
B BX BY NaN NaN
C NaN NaN CX CZ

์—ฌ๋Ÿฌ๊ฐ€์ง€ ํŒ

  • ๋ฐ์ดํ„ฐ ์ •๋ฆฌ ๋•Œ, index์™€ column์„ ์„œ๋กœ ๋’ค๋ฐ”๊ฟ€ ๋•Œ
df.T # Transpose ์‚ฌ์šฉ
  • ๋ฐ์ดํ„ฐ์˜ ์ฒซ๋ฒˆ์งธ ํ–‰์„ index๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ
new_header = df.iloc[0] # grab the first row for the header
df = df[1:] # take the data less the header row
df.columns = new_header # set the header row as the df header

Merge


merge๋Š” ๊ณตํ†ต๋œ ๋ถ€๋ถ„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ์น˜๋Š” ์šฉ๋„!!! (concat๋„ ํ•ฉ์น˜๊ธด ํ•˜์ง€๋งŒ, ์„œ๋กœ ์—†๋Š” index ๋ฐ column์— ๋Œ€ํ•ด์„œ NaN์œผ๋กœ ํ•ด์„œ ํ•ฉ์ณค๋‹ค.)

df.merge('๋ถ™์ผ๋‚ด์šฉ', how='(๋ฐฉ๋ฒ•)', on='(๊ธฐ์ค€์œผ๋กœ ์‚ผ์„ feature)')
df = df.merge(df2, how='inner', on='์นผ๋Ÿผ1') # ์ด๋Ÿฐ์‹์œผ๋กœ, ๋‹จ df๋ฅผ ๊ธฐ์ค€์œผ๋กœ df2๋ฅผ ์–ด๋–ป๊ฒŒ ๋ถ™์ด๋Š”์ง€ ์ข…๋ฅ˜๊ฐ€ ์—ฌ๋Ÿฌ๊ฐ€์ง€์ด๋‹ค.


๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ์ด๋Ÿฐ์‹!!!

Conditioning(์ด๊ฑด ์˜ˆ์‹œ๋กœ ๊ฐ€๋ณ๊ฒŒ ํ•œ๋ฒˆ ๋ณด์ž)

์šฐ๋ฆฌ๊ฐ€ ์ด๋Ÿฐ ๊ฒŒ ๊ถ๊ธˆํ•ด์ง

  1. ์ฃผ์‹ ์ข…๋ชฉ๋“ค์˜ ํ‰๊ท  ์ˆœ์ด์ต๋ฅ ์€ ์–ผ๋งˆ์ผ๊นŒ
  2. ๋‹จ, ์ˆœ์ด์ต๋ฅ ์ด - ์ธ ์ข…๋ชฉ์€ ์ œ์™ธํ•˜๊ณ  ๊ณ„์‚ฐ
  3. ํ…Œ๋งˆ๋ณ„๋กœ
# ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ํ•„ํ„ฐ๋ง ์˜ˆ์‹œ

# type cast
df['์ˆœ์ด์ต๋ฅ '] = pd.to_numeric(df['์ˆœ์ด์ต๋ฅ '])

# ํ•„ํ„ฐ๋ง ์กฐ๊ฑด (Condition) ์„ค์ •
condition = (df['์ˆœ์ด์ต๋ฅ '] > 0) # Type Cast
# () ๋กœ ์”Œ์šฐ๋Š”๊ฒƒ์— ์ฃผ์˜

## condition ์˜ ๊ฐ’์„ ์ถœ๋ ฅ์„ ํ†ตํ•ด ํ™•์ธํ•ด๋ณด์„ธ์š”. 

# [ ] ์•ˆ์— ์ปจ๋””์…˜์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ, ์ปจ๋””์…˜์˜ ๊ฐ’์ด *TRUE*๋กœ ํ•ด๋‹นํ•˜๋Š” ๋ถ€๋ถ„์˜ ๋ฐ์ดํ„ฐ๋งŒ ์„ ํƒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
df_subset = df[condition]

# ๊ฒฐ๊ณผ๋ฌผ์„ ํ™•์ธ
df_subset

์ด๋ ‡๊ฒŒ ๋™์‹œ์— ์ ์šฉ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ  condition ๋ณ€์ˆ˜์— ์•ˆ๋„ฃ๊ณ  ๊ทธ๋ƒฅ ๋ฐ”๋กœ ์จ๋„ ๋ฌด๋ฐฉ. ๋Œ€์‹  ์ข€ ์ง€์ €๋ถ„

condition = ( (df['์ˆœ์ด์ต๋ฅ '] > 0) & (df['์ˆœ์ด์ต๋ฅ '] < 10))

isin

  • ์กฐ๊ธˆ trickyํ•œ condition์„ ์„ค์ •ํ•ด๋ณด๊ธฐ(์˜ˆ์‹œ)
    df[df['ํ…Œ๋งˆ'].isin(['์ฃผ๋ฅ˜'])] 
    ์ฆ‰, 'ํ…Œ๋งˆ' ์นผ๋Ÿผ์—์„œ '์ฃผ๋ฅ˜' ๊ฐ’์„ ๊ฐ–๋Š” ์• ๋“ค๋งŒ ๊ณจ๋ผ์คŒ

์ด๊ฑธ condition์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด

df[(df['ํ…Œ๋งˆ'] == '์ฃผ๋ฅ˜')]

์ด๋ ‡๊ฒŒ ์“ฐ๋ฉด ๋จ

Groupby

์•„๋ž˜ ์กฐ๊ฑด ์ค‘ conditioning์„ ํ†ตํ•ด 2๋ฒˆ๊นŒ์ง€๋Š” ์™„๋ฃŒ

  1. ์ฃผ์‹ ์ข…๋ชฉ๋“ค์˜ ํ‰๊ท  ์ˆœ์ด์ต๋ฅ ์€ ์–ผ๋งˆ์ผ๊นŒ
  2. ๋‹จ, ์ˆœ์ด์ต๋ฅ ์ด - ์ธ ์ข…๋ชฉ์€ ์ œ์™ธํ•˜๊ณ  ๊ณ„์‚ฐ
  3. ํ…Œ๋งˆ๋ณ„๋กœ

์ด์ œ 3๋ฒˆ์„ ํ•  ์ฐจ๋ก€

์ข…๋ชฉ ๋งค์ถœ์•ก ์ˆœ์ด์ต๋ฅ  ์ข…๋ชฉ๋ช… ํ…Œ๋งˆ
0 000080 6,243 5.17 ํ•˜์ดํŠธ์ง„๋กœ ์ฃผ๋ฅ˜
1 000890 205 2.15 ๋ณดํ•ด์–‘์กฐ ์ฃผ๋ฅ˜
2 005300 5,980 2.59 ๋กฏ๋ฐ์น ์„ฑ ์ฃผ๋ฅ˜
4 035810 4,108 16.00 ์ด์ง€ํ™€๋”ฉ์Šค ์œก๊ณ„
5 136480 2,613 2.51 ํ•˜๋ฆผ ์œก๊ณ„

๋ผ๊ณ  ํ•  ๋•Œ,

df.groupby('ํ…Œ๋งˆ').์ˆœ์ด์ต๋ฅ .mean()

ํ…Œ๋งˆ
์œก๊ณ„ 9.255000
์ฃผ๋ฅ˜ 3.303333
Name: ์ˆœ์ด์ต๋ฅ , dtype: float64

์œ„์™€ ๊ฐ™์ด ํ…Œ๋งˆ์— ๋”ฐ๋ฅธ ์ˆœ์ด์ต๋ฅ ์˜ ํ‰๊ท ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.

์—ฌ๊ธฐ์„œ ํ•˜๋‚˜ ๋˜ ์•Œ์•„๋‘๊ณ  ๊ฐ€๋ฉด ์ข‹์€ ์ 

df_subset.groupby('ํ…Œ๋งˆ').mean()

๋ผ๊ณ  ํ•˜๋ฉด

์ˆœ์ด์ต๋ฅ 

ํ…Œ๋งˆ
์œก๊ณ„ 9.255000
์ฃผ๋ฅ˜ 3.303333

๊ณผ ๊ฐ™์€ dataframe ํ˜•ํƒœ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค. ์™œ ๊ทธ๋Ÿฐ๊ฑธ๊นŒ?
์ผ๋‹จ ๊ธฐ๋ณธ์ ์œผ๋กœ meanํ•จ์ˆ˜๋Š” ์ˆซ์žํ˜• ์นผ๋Ÿผ์— ๋Œ€ํ•ด์„œ๋งŒ ์ ์šฉ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” '์ˆœ์ด์ต๋ฅ ' ์นผ๋Ÿผ๋งŒ ์ˆซ์žํ˜•์ด๋ผ ์ด๋ ‡๊ฒŒ ๋‚˜์˜ค๊ณ 
์‹ค์ œ ๋‹ค๋ฅธ ์นผ๋Ÿผ๋„ ์ˆซ์žํ˜•์ด ์žˆ๋‹ค๋ฉด ๊ทธ ์นผ๋Ÿผ๊นŒ์ง€ ์ถ”๊ฐ€ํ•ด์„œ ํ…Œ๋งˆ๋ฅผ ์ธ๋ฑ์Šค๋กœ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์ด ๋‚˜์˜ค๊ฒŒ๋œ๋‹ค.

์ž ์ด์ œ ์ค‘์š”ํ•œ ํƒ€์ด๋”” ์™€์ด๋“œ ๋ณ€ํ™˜ ๊ณผ์ • ๋ณด์ž!!! ์—ฌ๊ธฐ ์ž˜ ๊ณต๋ถ€ํ•˜์ž!!!

๋“ค์–ด๊ฐ€๊ธฐ์— ์•ž์„œ ๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋ฅผ ์™œ ๊ตณ์ด ๋ฐ”๊ฟ”์•ผํ•˜๋‚˜?
์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”๋กœ ํ•œ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ ์‹œ๊ฐํ™”์— ์“ฐ์ด๋Š” Seaborn ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” 'Tidy ๋ฐ์ดํ„ฐ'๋ฅผ ํ•„์š”๋กœ ํ•œ๋‹ค.
(๋ฌผ๋ก  ํ•ญ์ƒ ๊ทธ๋Ÿฐ ๊ฒƒ์€ ์•„๋‹˜)

Tidy ๋ฐ์ดํ„ฐ ์™€ Wide ๋ฐ์ดํ„ฐ

X,Y,Z์—๊ฒŒ A,B๋ผ๋Š” ์•ฝ์„ ํˆฌ์—ฌํ•ด์„œ ๋ฐ˜์‘์„ ์•Œ์•„๋ณธ๋‹ค.

ํ–‰์—๋Š” ๊ด€์ธก, ์—ด์—๋Š” feature ํ ... ์•„์ง ์กฐ๊ธˆ ํ—ท๊ฐˆ๋ฆฐ๋‹ค... ์šฐ๋ฆฌ๊ฐ€ ํ”ํžˆ ๋ณด๋Š” df๋“ค์ด tidyํ˜•ํƒœ์ธ๊ฑด๊ฐ€..? ์ข€๋” ์ƒ๊ฐํ•ด๋ณด์ž

wideํ•œ ๋ฐ์ดํ„ฐ๋Š” ์‹ค์ œ๋กœ ์•ผ์ƒ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ
tidy๋Š” ์ด์ œ ๊ทธ๊ฑธ ์šฐ๋ฆฌ๊ฐ€ ๋ถ„์„ํ•˜๊ธฐ ์šฉ์ดํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๋Š” ๋Š๋‚Œ?? ์ด๋ ‡๊ฒŒ ์ •๋ฆฌํ•˜๋ฉด index์— 0๋ถ€ํ„ฐ ์ˆซ์ž๊ฐ€ ๋“ค์–ด๊ฐˆํ…Œ๋‹ˆ ์šฐ๋ฆฌ๊ฐ€ ํ‰์†Œ ๋ณด๋Š” ๊ทธ ๋ฐ์ดํ„ฐ๋ชจ์Šต์€๋“ฏ?

Wide์—์„œ Tidy๋กœ

pandas์˜ melt ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
์œ„์˜ X,Y,Z/A,B ํ…Œ์ด๋ธ”์„ ์˜ˆ์‹œ๋กœ ๋“ค๋ฉด

### ํ–‰์˜ ์ธ๋ฑ์Šค๋ฅผ ์„ ํƒํ•˜๊ณ , ์ด๋ฅผ ํ–‰์œผ๋กœ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
tidy1 = wide1.reset_index() # rownames๋ฅผ ์ƒˆ๋กœ ์„ค์ • 

๋ฅผ ์ ์šฉํ•˜๋ฉด

index A B
0 X NaN 2
1 Y 16.0 11
2 Z 3.0 1

์™€ ๊ฐ™์ด ๋œ๋‹ค. ์ดํ›„

tidy๋Š” ํ•œ ํ–‰์—, ํ•œ observation์„ ๊ฐ–๊ฒŒ ํ•˜๋Š” ๊ฒƒ
ํ•œ observation์—๋Š” ์–ด๋–ค ๊ฐ’์ด ์žˆ์–ด์•ผํ• ๊นŒ
๋ˆ„๊ฐ€(id), ์–ด๋–ค feature๊ฐ’์„ ๊ฐ€์ง€๋Š”์ง€(value) Column์„ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

์ด๋ฅผ melt๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

### ๊ฐ ํ–‰์— ๋Œ€ํ•ด์„œ (unique identifier)๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
### ํ•œ๊ฐœ์˜ "tidy" ํ•œ ์—ด์— ๋Œ€ํ•ด์„œ ํฌํ•จ๋˜์–ด์•ผ ํ•  (๊ธฐ์ค€์ด ๋˜๋Š”) ๋ฐ์ดํ„ฐ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
tidy2 = tidy1.melt(id_vars = 'index', value_vars = ['A', 'B'])

๊ทธ๋Ÿฌ๋ฉด

index variable value
0 X A NaN
1 Y A 16.0
2 Z A 3.0
3 X B 2.0
4 Y B 11.0
5 Z B 1.0

์™€ ๊ฐ™์ด ๋œ๋‹ค. ๊ทธ ํ›„ column์˜ ์ด๋ฆ„์„ ์ •๋ฆฌํ•ด์ฃผ๋ฉด ๋œ๋‹ค.


์œ„ ์‚ฌ์ง„๊ณผ ๊ฐ™์€ ๋Š๋‚Œ(ํ ... ์•„์ง ์ซŒ ํ—ท๊ฐˆ๋ฆฌ๋„ค... ์—ฌ๊ธฐ ์ง„์งœ ๋” ๊ณต๋ถ€ํ•ด์•ผ๊ฒ ๋‹ค)

Tidy์—์„œ Wide๋กœ

pivot_table ํ•จ์ˆ˜๋Š” melt ํ•จ์ˆ˜์˜ ๋ฐ˜๋Œ€ ์—ญํ• ์„ ํ•˜๋Š” ํ•จ์ˆ˜!

# ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋Œ€ํ•œ ์„ค๋ช…
# index: unique identifier
# columns: "wide" ๋ฐ์ดํ„ฐ์—์„œ column๋ณ„๋กœ ๋‹ค๋ฅด๊ฒŒ ํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฐ’.
# values: ๊ฒฐ๊ณผ๊ฐ’์ด ๋“ค์–ด๊ฐ€๋Š” ๊ณณ (wide ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์˜ ๋‚ด์šฉ์— ๋“ค์–ด๊ฐˆ ๊ฐ’)
wide = tidy2.pivot_table(index = 'row', columns = 'column', values = 'value')

๊ทธ๋Ÿฌ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌ๋จ

column A B
row
X NaN 2.0
Y 16.0 11.0
Z 3.0 1.0

Tidy ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“œ๋Š” ์ด์œ 

์˜ˆ๋ฅผ ๋“ค๋ฉด
seaborn๊ณผ ๊ฐ™์€ ์‹œ๊ฐํ™” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค.

import seaborn as sns
sns.catplot(x = 'row', y = 'value', col = 'column', kind = 'bar', data = tidy1, height = 2);

์ด๋ ‡๊ฒŒ tidy ํ˜•ํƒœ์—ฌ์•ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•˜๊ธฐ ํŽธ๋ฆฌํ•˜๋‹ค.