๐Ÿผ ๋ฐ์ดํ„ฐ ๋ถ„์„๊ณผ Python: Pandas ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ

Geondong Kimยท4์ผ ์ „
post-thumbnail

๐Ÿผ ๋ฐ์ดํ„ฐ ๋ถ„์„๊ณผ Python: Pandas ์‹ฌํ™” (Part 3)

1. ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ (Data Preprocessing)

1.1 ํ•„์š”์„ฑ

  • ์›์‹œ ๋ฐ์ดํ„ฐ(Raw Data)๋Š” ๋ถ„์„์— ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค (์ •ํ˜•ํ™”๋˜์ง€ ์•Š์Œ).
  • ๊ฒฐ์ธก์น˜(Missing Values), ์ด์ƒ์น˜(Outliers) ๋“ฑ์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐ’์˜ ๋ถˆ์ผ์น˜: ์˜ˆ) '๋‚จ'/'๋‚จ์ž', '๊ฒฝ๋ถ'/'๊ฒฝ์ƒ๋ถ๋„' ๋“ฑ ํ†ต์ผ๋˜์ง€ ์•Š์€ ๊ฐ’.
  • ๋ชฉ์ : ๋ถ„์„์˜ ์ •ํ™•๋„ ๋ฐ ๋ชจ๋ธ ์„ฑ๋Šฅ ํ–ฅ์ƒ. (์ „์ฒ˜๋ฆฌ๊ฐ€ ์ „์ฒด ๋ถ„์„ ๊ณผ์ •์˜ 70% ์ด์ƒ์„ ์ฐจ์ง€)
  • ์›์น™: Garbage In, Garbage Out (์“ฐ๋ ˆ๊ธฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€๋ฉด ์“ฐ๋ ˆ๊ธฐ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค).

1.2 ์ž๋ฃŒํ˜• ๋ณ€ํ™˜ (Type Casting)

๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ–ˆ์„ ๋•Œ ์ˆซ์ž๊ฐ€ ๋ฌธ์ž์—ด๋กœ ์ธ์‹๋˜๊ฑฐ๋‚˜, ๋‚ ์งœ๊ฐ€ ๊ฐ์ฒด(Object)๋กœ ์ธ์‹๋˜๋Š” ๊ฒฝ์šฐ ์˜ฌ๋ฐ”๋ฅธ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ์ •ํ™•ํ•œ ์—ฐ์‚ฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • astype(): ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ช…์‹œ์  ํ˜•๋ณ€ํ™˜ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.
    • df.astype('int32') ๋˜๋Š” df.astype({'col1': 'int32'})

      # ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์˜ ์ž๋ฃŒํ˜• ๋ณ€ํ™˜
      # DataFrame.astype(dtype, copcy=None, errors='raise')
      
      # ์‹œ๋ฆฌ์ฆˆ์˜ ์ž๋ฃŒํ˜• ๋ณ€ํ™˜
      # Series.astype(dtype, copy=None, erros='raise')
      
      # ๋‹จ์ผ ์ปฌ๋Ÿผ ๋ณ€ํ™˜
      df['col1'] = df['col1'].astype('int32')
      
      # ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์ด์šฉํ•œ ๋‹ค์ค‘ ์ปฌ๋Ÿผ ๋ณ€ํ™˜
      df = df.astype({'col1': 'int32', 'col2': 'float64'})
      
      # ๋ฒ”์ฃผํ˜• ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ (๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ ๋ฐ ๋ถ„์„ ํšจ์œจ์„ฑ ์ฆ๋Œ€)
      df['category_col'] = df['category_col'].astype('category')
  • to_numeric, to_datetime, to_timedelta: ํŠน์ • ํƒ€์ž…์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋“ค.
    • to_numeric: ๋ฌธ์ž์—ด์ด ์„ž์—ฌ ์žˆ์„ ๋•Œ errors='coerce' ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณ€ํ™˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฐ’์€ NaN์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ์•ˆ์ „ํ•˜๊ฒŒ ์ˆซ์ž๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Tip: copy ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ํ–ฅํ›„ Copy-on-Write ๋ฐฉ์‹์œผ๋กœ ๋Œ€์ฒด๋  ์˜ˆ์ •์ด๋ฏ€๋กœ ์‚ฌ์šฉ์„ ์ง€์–‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
  • convert_dtypes(): ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ์ ์ ˆํ•œ ํƒ€์ž…(์˜ˆ: nullable int, string)์œผ๋กœ ์ž๋™ ๋ณ€ํ™˜์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์‹  Pandas์—์„œ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ์‹ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

1.3 ๊ฒฐ์ธก์น˜ ๋ฐ ์ค‘๋ณต ์ฒ˜๋ฆฌ (Cleanming)

  • ๊ฒฐ์ธก์น˜ ํ™•์ธ: df.isna() ๋˜๋Š” df.isnull()
  • ๊ฒฐ์ธก์น˜ ์‚ญ์ œ (dropna):
    • df.dropna(axis=0): ๊ฒฐ์ธก์น˜๊ฐ€ ์žˆ๋Š” ํ–‰ ์‚ญ์ œ.
    • df.dropna(how='all'): ๋ชจ๋“  ๊ฐ’์ด ๊ฒฐ์ธก์น˜์ธ ๊ฒฝ์šฐ๋งŒ ์‚ญ์ œ.
    • df.dropna(thresh=N): ์ •์ƒ ๋ฐ์ดํ„ฐ๊ฐ€ N๊ฐœ ์ด์ƒ์ด๋ฉด ์œ ์ง€.
  • ๊ฒฐ์ธก์น˜ ์ฑ„์šฐ๊ธฐ (fillna):
    • df.fillna(0): 0์œผ๋กœ ์ฑ„์›€.
    • df.fillna(df.mean()): ํ‰๊ท ๊ฐ’์œผ๋กœ ๋Œ€์ฒด.
    • ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ: ffill()(์•ž์˜ ๊ฐ’์œผ๋กœ ์ฑ„์›€), bfill()(๋’ค์˜ ๊ฐ’์œผ๋กœ ์ฑ„์›€).
  • ์ค‘๋ณต ์ œ๊ฑฐ:
    • df.drop_duplicates(subset=['col1', 'col2'], keep='first'): ํŠน์ • ์ปฌ๋Ÿผ ๊ธฐ์ค€ ์ค‘๋ณต ์ œ๊ฑฐ.

2. ๋ฐ์ดํ„ฐ ๊ทธ๋ฃนํ™” (Grouping): Split-Apply-Combine

๋ฐ์ดํ„ฐ๋ฅผ ํŠน์ • ๊ธฐ์ค€์— ๋”ฐ๋ผ ๋‚˜๋ˆ„๊ณ (Split), ๊ฐ ๊ทธ๋ฃน์— ์—ฐ์‚ฐ์„ ์ ์šฉํ•˜๊ณ (Apply), ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ํ•ฉ์น˜๋Š”(Combine) ๊ฐ•๋ ฅํ•œ ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

2.1 GroupBy ๊ฐ์ฒด ์ƒ์„ฑ (groupby())

# ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ๊ฐ์ฒด ์ƒ์„ฑ
# DataFrame.groupby(by=None, axis=<no_default> , level=None, as_index=True, 
#                   sort=True, group_keys=True, observed=<no_default> , dropna=True)

grouped = df.groupby('Key_Column')
# ์—ฌ๋Ÿฌ ์ปฌ๋Ÿผ ๊ธฐ์ค€
grouped = df.groupby(['Key1', 'Key2'])

2.2 GroupBy์˜ ์ฒซ ๋‹จ๊ณ„: Split (๋ฐ์ดํ„ฐ ๋ถ„ํ• )

Split ๋‹จ๊ณ„๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํŠน์ • ๊ธฐ์ค€(Key)์— ๋”ฐ๋ผ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ ์ฆ‰์‹œ ๊ณ„์‚ฐ์ด ์ˆ˜ํ–‰๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ, GroupBy ๊ฐ์ฒด(์ค‘๊ฐ„์ฒด) ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

โ‘  ๋‹ค์–‘ํ•œ ๋ถ„ํ•  ๊ธฐ์ค€ (by ํŒŒ๋ผ๋ฏธํ„ฐ)

Pandas๋Š” ๋งค์šฐ ์œ ์—ฐํ•œ ๋ถ„ํ•  ๊ธฐ์ค€์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ๋‹จ์ผ ์ปฌ๋Ÿผ: ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.
    # 'School' ์ปฌ๋Ÿผ์˜ ๊ฐ’(์˜ˆ: A๊ณ ๊ต, B๊ณ ๊ต)์„ ๊ธฐ์ค€์œผ๋กœ ๋‚˜๋ˆ”
    grouped = df.groupby('School')
  • ๋‹ค์ค‘ ์ปฌ๋Ÿผ: ์—ฌ๋Ÿฌ ์ปฌ๋Ÿผ์„ ๊ณ„์ธต์ ์œผ๋กœ ๋ฌถ์Šต๋‹ˆ๋‹ค.
    # 'School'๋กœ ๋จผ์ € ๋‚˜๋ˆ„๊ณ , ๊ทธ ์•ˆ์—์„œ 'Grade'๋กœ ๋‹ค์‹œ ๋‚˜๋ˆ”
    grouped = df.groupby(['School', 'Grade'])
  • ํ•จ์ˆ˜(Function) ๋˜๋Š” ๋งคํ•‘(Dict): ์ธ๋ฑ์Šค(Index)์— ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•˜๊ฑฐ๋‚˜ ๋”•์…”๋„ˆ๋ฆฌ๋กœ ๊ทธ๋ฃน์„ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    # ์ธ๋ฑ์Šค๊ฐ€ ๋‚ ์งœ์ผ ๋•Œ, ์—ฐ๋„(year)๋ณ„๋กœ ๊ทธ๋ฃนํ•‘
    df.groupby(lambda x: x.year)
    
    # ๋”•์…”๋„ˆ๋ฆฌ๋กœ ์ธ๋ฑ์Šค ๋งคํ•‘ (a, b๋Š” 'First', c๋Š” 'Second' ๊ทธ๋ฃน)
    mapping = {'a': 'First', 'b': 'First', 'c': 'Second'}
    df.groupby(mapping)

โ‘ก Split๋œ ๊ฒฐ๊ณผ ํ™•์ธํ•˜๊ธฐ (Inspection)

GroupBy ๊ฐ์ฒด๋Š” ๊ฒ‰์œผ๋กœ ๋ณด๊ธฐ์—” ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋ณด์ด์ง€๋งŒ, ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๊ทธ๋ฃน ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•๋“ค์ž…๋‹ˆ๋‹ค.

  • groups ์†์„ฑ: ๊ฐ ๊ทธ๋ฃน์˜ ์ด๋ฆ„(Key)๊ณผ ํ•ด๋‹น ๋ฐ์ดํ„ฐ์˜ ์ธ๋ฑ์Šค(Label)๋ฅผ ๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
    print(grouped.groups)
    # ๊ฒฐ๊ณผ: {'A๊ณ ๊ต': [0, 2, 5], 'B๊ณ ๊ต': [1, 3, 4]}
  • get_group() ๋ฉ”์„œ๋“œ: ํŠน์ • ๊ทธ๋ฃน์˜ ๋ฐ์ดํ„ฐ๋งŒ DataFrame์œผ๋กœ ์ถ”์ถœํ•ด ๋ด…๋‹ˆ๋‹ค. (๋””๋ฒ„๊น…ํ•  ๋•Œ ์œ ์šฉ)
    # 'A๊ณ ๊ต' ๊ทธ๋ฃน์— ์†ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ํ™•์ธ
    a_school_data = grouped.get_group('A๊ณ ๊ต')
  • ๋ฐ˜๋ณต๋ฌธ(Iteration): for ๋ฌธ์„ ํ†ตํ•ด (๊ทธ๋ฃน๋ช…, ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„) ์Œ์„ ์ˆœํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    for name, group_df in grouped:
        print(f"Group Name: {name}")
        print(group_df.head()) # ๊ฐ ๊ทธ๋ฃน์˜ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ

โ‘ข Split์˜ ํŠน์ง•

  • Lazy Evaluation (์ง€์—ฐ ์—ฐ์‚ฐ): groupby()๋งŒ ์‹คํ–‰ํ–ˆ์„ ๋•Œ๋Š” ์‹ค์ œ ํ†ต๊ณ„ ์—ฐ์‚ฐ(ํ‰๊ท , ํ•ฉ๊ณ„ ๋“ฑ)์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. sum(), mean() ๊ฐ™์€ Apply ๋‹จ๊ณ„์˜ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ๋น„๋กœ์†Œ ์—ฐ์‚ฐ์ด ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.
  • Nan ์ฒ˜๋ฆฌ: ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ทธ๋ฃน ํ‚ค(Key)์— NaN(๊ฒฐ์ธก์น˜)์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉด, ํ•ด๋‹น ํ–‰์€ ๊ทธ๋ฃน์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. (์˜ต์…˜ dropna=False๋ฅผ ์ฃผ๋ฉด NaN๋„ ํ•˜๋‚˜์˜ ๊ทธ๋ฃน์œผ๋กœ ์ธ์ •ํ•ฉ๋‹ˆ๋‹ค.)

2.3 Apply ๋‹จ๊ณ„์˜ 3๊ฐ€์ง€ ์œ ํ˜•

โ‘  Aggregation (์ง‘๊ณ„)

๊ทธ๋ฃน๋ณ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์•ฝํ•˜์—ฌ ํ•˜๋‚˜์˜ ์Šค์นผ๋ผ ๊ฐ’์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

  • ๊ธฐ๋ณธ ํ•จ์ˆ˜: sum(), mean(), std(), min(), max(), size()
  • agg() ์‚ฌ์šฉ: ์—ฌ๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ๋™์‹œ์— ์ ์šฉํ•˜๊ฑฐ๋‚˜ ์ปฌ๋Ÿผ๋ณ„๋กœ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
    # ์ปฌ๋Ÿผ๋ณ„ ๋‹ค๋ฅธ ์—ฐ์‚ฐ ์ ์šฉ
    df.groupby("kind").agg(
        min_height=("height", "min"),
        avg_weight=("weight", "mean")
    )

โ‘ก Transformation (๋ณ€ํ™˜)

๊ทธ๋ฃน๋ณ„๋กœ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์ •๊ทœํ™” (cumsum, diff ๋“ฑ)๋ฅผ ์ˆ˜ํ–‰ํ•˜๋˜, ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๊ฐ€ ์›๋ณธ๊ณผ ๋™์ผํ•˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๊ฐ ํ–‰์— ๊ทธ๋ฃน๋ณ„ ํŠน์„ฑ์„ ๋ฐ˜์˜ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ์˜ˆ์‹œ: ๊ทธ๋ฃน๋ณ„ ํ‰๊ท ์œผ๋กœ ๊ฒฐ์ธก์น˜ ์ฑ„์šฐ๊ธฐ, ๊ทธ๋ฃน ๋‚ด ์ •๊ทœํ™”(Z-score).
    # ๊ฐ ๊ทธ๋ฃน์˜ ํ‘œ์ค€ํŽธ์ฐจ๋กœ ๋‚˜๋ˆ„๊ธฐ (Standardization)
    df.groupby('A').transform(lambda x: (x - x.mean()) / x.std())
    
    # ๊ฐ ๊ทธ๋ฃน ๋‚ด์—์„œ ๋ˆ„์  ํ•ฉ ๊ณ„์‚ฐ
    grouped.cumsum()

โ‘ข Filtration (ํ•„ํ„ฐ๋ง)

์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ์•Š๋Š” ๊ทธ๋ฃน ์ „์ฒด๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. (loc ๋“ฑ์„ ์ด์šฉํ•œ ํ–‰ ๋‹จ์œ„ ํ•„ํ„ฐ๋ง๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.)

  • ์˜ˆ์‹œ: ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๊ฐ€ 3๊ฐœ ๋ฏธ๋งŒ์ธ ๊ทธ๋ฃน์€ ๋ถ„์„์—์„œ ์ œ์™ธ.
    # ๊ทธ๋ฃน ๋‚ด ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜(len)๊ฐ€ 2๋ณด๋‹ค ํฐ ๊ทธ๋ฃน๋งŒ ๋‚จ๊น€
    df.groupby("B").filter(lambda x: len(x) > 2)

โ‘ฃ Apply (์œ ์—ฐํ•œ ์ ์šฉ)

๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค. ์ž„์˜์˜ ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฒฐ๊ณผ ํ˜•ํƒœ๊ฐ€ ์œ ๋™์ ์ž…๋‹ˆ๋‹ค. ๋‹ค๋งŒ, ์†๋„๊ฐ€ ๋А๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# DataFrameGroupBy.apply(func, *args, include_groups=True, **kwargs)
  • Tip: ์ตœ์‹  Pandas์—์„œ๋Š” include_groups=False๋ฅผ ์ง€์ •ํ•˜์—ฌ ๊ทธ๋ฃนํ•‘ ํ‚ค๊ฐ€ ๊ฒฐ๊ณผ์— ์ค‘๋ณต ํฌํ•จ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

2.4 Combine (๊ฒฐํ•ฉ): ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ํ†ตํ•ฉํ•ฉ๋‹ˆ๋‹ค.


3. ๋ฐ์ดํ„ฐ ์žฌ๊ตฌ์กฐํ™” (Reshaping)

๋ฐ์ดํ„ฐ์˜ ํ˜•ํƒœ๋ฅผ ๋ถ„์„ ๋ชฉ์ ์— ๋งž๊ฒŒ ๋ณ€๊ฒฝํ•˜๋Š” ๊ธฐ๋Šฅ๋“ค์ž…๋‹ˆ๋‹ค.

3.1 Pivot & Melt (Long & Wide)

  • pivot: ๋ฐ์ดํ„ฐ์˜ ํŠน์ • ์ปฌ๋Ÿผ ๊ฐ’์„ ์ƒˆ๋กœ์šด ์ปฌ๋Ÿผ ํ—ค๋”๋กœ ๋งŒ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฅผ ์š”์•ฝ/์žฌ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์„ธ๋กœ๋กœ ๊ธด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋กœ๋กœ ๋„“๊ฒŒ ํŽผ์นฉ๋‹ˆ๋‹ค. (Long to Wide)
    • ์‚ฌ์šฉ์ฒ˜: ์š”์•ฝํ‘œ ์ƒ์„ฑ, ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ ์ •๋ฆฌ.

    • ์ฃผ์˜: ์ค‘๋ณต๋œ ์ธ๋ฑ์Šค/์ปฌ๋Ÿผ ์Œ์ด ์žˆ์œผ๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ง‘๊ณ„ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋œ pivot_table()์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

      # DataFrame.pivot(*, columns, index=<no_default>, values=<no_default>)
      
      df.pivot(index='date', columns='variable', values='value')
  • melt: ์—ฌ๋Ÿฌ ์ปฌ๋Ÿผ์„ ํ•˜๋‚˜์˜ ์ปฌ๋Ÿผ์œผ๋กœ ๋…น์—ฌ์„œ ํ–‰์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ฐ€๋กœ๋กœ ๋„“์€ ๋ฐ์ดํ„ฐ๋ฅผ ์„ธ๋กœ๋กœ ๊ธธ๊ฒŒ ๋…น์ž…๋‹ˆ๋‹ค. ์ปดํ“จํ„ฐ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์ข‹์€ ํ˜•ํƒœ(Tidy Data)๋กœ ๋ฐ”๊ฟ€ ๋•Œ ์”๋‹ˆ๋‹ค. (Wide to Long)
    • id_vars: ๊ธฐ์ค€์ด ๋ (์œ ์ง€ํ• ) ์ปฌ๋Ÿผ.

    • value_vars: ๋…น์—ฌ์„œ ํ–‰์œผ๋กœ ๋งŒ๋“ค ์ปฌ๋Ÿผ.

      # DataFrame.melt(id_vars=None, value_vars=None, var_name=None, 
      #                value_name='value', col_level=None, ignore_index=True)

3.2 Stack & Unstack

  • stack: ์ปฌ๋Ÿผ(์—ด) ๋ ˆ๋ฒจ์„ ์ธ๋ฑ์Šค(ํ–‰) ๋ ˆ๋ฒจ๋กœ ์••์ถ•ํ•ฉ๋‹ˆ๋‹ค. (Columns โ†’\to Index)
  • unstack: ์ธ๋ฑ์Šค(ํ–‰) ๋ ˆ๋ฒจ์„ ์ปฌ๋Ÿผ(์—ด) ๋ ˆ๋ฒจ๋กœ ํŽผ์นฉ๋‹ˆ๋‹ค. (Index โ†’\to Columns)
    • groupby ํ›„ unstack()์„ ์ž์ฃผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
# DataFrame.stack(level=-1, dropna=<no_default>, sort=<no_default>, futures_tack=False)
# DataFrame.unstack(level=-1, fill_value=None, sort=True)

3.3 Explode

  • explode: ๋ฆฌ์ŠคํŠธ๋‚˜ ๋ฐฐ์—ด ํ˜•ํƒœ์˜ ๊ฐ’์„ ๊ฐ€์ง„ ์ปฌ๋Ÿผ์„ ์—ฌ๋Ÿฌ ํ–‰์œผ๋กœ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค. (1ํ–‰ โ†’\to Nํ–‰)
    # DataFrame.explode(column, ignore_index=False)
    
    # Before
    # A  | B
    # 1  | [a, b]
    
    df.explode('B')
    
    # After
    # A | B
    # 1 | a
    # 1 | b

4. ๋ฐ์ดํ„ฐ ๋ณ‘ํ•ฉ (Merge & Concat)

4.1 merge (SQL Join ๋ฐฉ์‹)

๋‘ DataFrame์„ ํŠน์ • ํ‚ค(Key)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ณ‘ํ•ฉํ•ฉ๋‹ˆ๋‹ค. SQL์˜ Join๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

# DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None, 
#                 left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'),
#                 copy=None, indicator=False, validate=None)
  • on: ๊ธฐ์ค€์ด ๋˜๋Š” ์ปฌ๋Ÿผ๋ช…. (๋‘ DF์˜ ์ปฌ๋Ÿผ๋ช…์ด ๋‹ค๋ฅด๋ฉด left_on, right_on ์‚ฌ์šฉ)
  • how:
    • 'inner': ๊ต์ง‘ํ•ฉ (๋‘ ๋ฐ์ดํ„ฐ์— ๋ชจ๋‘ ์žˆ๋Š” ํ‚ค๋งŒ ๋‚จ๊น€). (๊ธฐ๋ณธ๊ฐ’)
    • 'outer': ํ•ฉ์ง‘ํ•ฉ (๋ชจ๋“  ํ‚ค๋ฅผ ๋‚จ๊ธฐ๊ณ , ๋นˆ ๊ณณ์€ NaN).
    • 'left': ์™ผ์ชฝ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์˜ ํ‚ค๋ฅผ ๋ชจ๋‘ ์œ ์ง€.
    • 'right': ์˜ค๋ฅธ์ชฝ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์˜ ํ‚ค๋ฅผ ๋ชจ๋‘ ์œ ์ง€.

4.2 concat (Concatenate, ๋ฌผ๋ฆฌ์  ๊ฒฐํ•ฉ)

๋‘ ๊ฐœ ์ด์ƒ์˜ DataFrame์„ ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์ด์–ด ๋ถ™์ž…๋‹ˆ๋‹ค.

# DataFrame.concat(objs, *, axis=0, join='outer', ignore_index=False, keys=None, 
#                  levels=None, names=None, verify_integrity=False, sort=False, copy=None)
  • axis=0(๊ธฐ๋ณธ๊ฐ’): ์œ„์•„๋ž˜๋กœ ๋ถ™์ด๊ธฐ (ํ–‰ ์ถ”๊ฐ€).
    • ignore_index=True: ๊ธฐ์กด ์ธ๋ฑ์Šค๋ฅผ ๋ฌด์‹œํ•˜๊ณ  ์ƒˆ๋กœ ๋ฒˆํ˜ธ๋ฅผ ๋งค๊ธฐ๊ธฐ.
  • axis=1: ์ขŒ์šฐ๋กœ ๋ถ™์ด๊ธฐ (์—ด ์ถ”๊ฐ€).
    • ์ธ๋ฑ์Šค๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋งค์นญํ•˜์—ฌ ๋ถ™์ž…๋‹ˆ๋‹ค.

5. ์ƒ๊ด€ ๋ถ„์„ (Correlation Analysis)

๋‘ ๋ณ€์ˆ˜ ๊ฐ„์˜ ๊ด€๊ณ„์˜ ๊ฐ•๋„์™€ ๋ฐฉํ–ฅ์„ ์ˆ˜์น˜ํ™”ํ•˜๋Š” ํ†ต๊ณ„ ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค.

5.1 ์ฃผ์š” ๊ฐœ๋…

  • ์ƒ๊ด€๊ณ„์ˆ˜ (rr): -1๊ณผ 1 ์‚ฌ์ด์˜ ๊ฐ’.
    • r=1r = 1: ์™„๋ฒฝํ•œ ์–‘์˜ ์ƒ๊ด€๊ด€๊ณ„ (X ์ฆ๊ฐ€ ์‹œ Y๋„ ์ฆ๊ฐ€).
    • r=โˆ’1r = -1: ์™„๋ฒฝํ•œ ์Œ์˜ ์ƒ๊ด€๊ด€๊ณ„ (X ์ฆ๊ฐ€ ์‹œ Y๋Š” ๊ฐ์†Œ).
    • r=0r = 0: ์„ ํ˜•์ ์ธ ๊ด€๊ณ„๊ฐ€ ์—†์Œ.
  • ์ฃผ์˜์‚ฌํ•ญ:
    • ์ธ๊ณผ ๊ด€๊ณ„๊ฐ€ ์•„๋‹˜: A์™€ B๊ฐ€ ๊ฐ™์ด ์›€์ง์ธ๋‹ค๊ณ  ํ•ด์„œ A๊ฐ€ B์˜ ์›์ธ์ธ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.
    • ์ด์ƒ์น˜(Outlier) ๋ฏผ๊ฐ์„ฑ: ์ด์ƒ์น˜๊ฐ€ ์žˆ์œผ๋ฉด ์ƒ๊ด€๊ณ„์ˆ˜๊ฐ€ ์™œ๊ณก๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

5.2 ์ƒ๊ด€๊ณ„์ˆ˜ ์ข…๋ฅ˜ (method ํŒŒ๋ผ๋ฏธํ„ฐ)

  1. Pearson (ํ”ผ์–ด์Šจ): ๊ธฐ๋ณธ๊ฐ’. ๋‘ ๋ณ€์ˆ˜ ๊ฐ„์˜ ์„ ํ˜•์  ๊ด€๊ณ„๋ฅผ ์ธก์ •. ์—ฐ์†ํ˜• ๋ฐ์ดํ„ฐ์— ์ ํ•ฉ.
  2. Spearman (์Šคํ”ผ์–ด๋งŒ): ๊ฐ’์˜ ์ˆœ์œ„(Rank)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ด€๊ณ„ ์ธก์ •. ๋น„์„ ํ˜• ๊ด€๊ณ„๋‚˜ ์ด์ƒ์น˜๊ฐ€ ์žˆ์„ ๋•Œ ์œ ์šฉ.
  3. Kendall (์ผ„๋‹ฌ): ์ˆœ์œ„ ๊ธฐ๋ฐ˜. ํ‘œ๋ณธ์ด ์ž‘์„ ๋•Œ Spearman๋ณด๋‹ค ๋” ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ์Œ.

5.2 corr() ๋ฉ”์„œ๋“œ

  • Pearson (๊ธฐ๋ณธ๊ฐ’): ์„ ํ˜•์ ์ธ ๊ด€๊ณ„ ์ธก์ •.
  • Spearman / Kendall: ์ˆœ์œ„ ๊ธฐ๋ฐ˜ ์ธก์ • (์ด์ƒ์น˜ ์˜ํ–ฅ์ด ์ ์Œ).
# DataFrame.corr(method='pearson', min_periods=1, numeric_only=False)

# ์ƒ๊ด€ ๊ณ„์ˆ˜ ํ–‰๋ ฌ ๊ณ„์‚ฐ
corr_matrix = df.corr(numeric_only=True)

# ์‹œ๊ฐํ™” (Seaborn Heatmap)
import seaborn as sns
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')

5.3 ์‹œ๊ฐํ™” (Heatmap)

์ƒ๊ด€ ๋ถ„์„ ๊ฒฐ๊ณผ๋Š” seaborn.heatmap์„ ํ†ตํ•ด ์‹œ๊ฐํ™”ํ•˜๋ฉด ๊ด€๊ณ„๋ฅผ ํ•œ๋ˆˆ์— ํŒŒ์•…ํ•˜๊ธฐ ์ข‹์Šต๋‹ˆ๋‹ค.

import seaborn as sns
import matplotlib.pyplot as plt

corr_matrix = df.corr(numeric_only=True) # ์ˆ˜์น˜ํ˜• ๋ฐ์ดํ„ฐ๋งŒ ๊ณ„์‚ฐ
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.show()

5.4 ์„ ํ˜• ํšŒ๊ท€ (Linear Regression)์™€์˜ ์ฐจ์ด

  • ์ƒ๊ด€ ๋ถ„์„: ๋‘ ๋ณ€์ˆ˜๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋ฐ€์ ‘ํ•˜๊ฒŒ ๊ด€๋ จ๋˜์–ด ์žˆ๋Š”์ง€(๊ด€๊ณ„์˜ ๊ฐ•๋„)๋งŒ ํ™•์ธ.
  • ์„ ํ˜• ํšŒ๊ท€: ํ•œ ๋ณ€์ˆ˜(๋…๋ฆฝ๋ณ€์ˆ˜)๋ฅผ ์ด์šฉํ•ด ๋‹ค๋ฅธ ๋ณ€์ˆ˜(์ข…์†๋ณ€์ˆ˜)๋ฅผ ์˜ˆ์ธก(Prediction)ํ•˜๊ธฐ ์œ„ํ•œ ์ˆ˜์‹(y=ax+by = ax + b)์„ ๋„์ถœ.

๐Ÿ”— ์ฐธ๊ณ  ์ž๋ฃŒ (References)

0๊ฐœ์˜ ๋Œ“๊ธ€