Skip to Content

Pandas (Python Data Analysis)

Python ์ƒํƒœ๊ณ„์—์„œ ๋ฐ์ดํ„ฐ ๋ถ„์„์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ Pandas์˜ ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ์›๋ฆฌ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

ํ•„์ˆ˜Internal

1. ํ•ต์‹ฌ ์ž๋ฃŒ๊ตฌ์กฐ (Core Structures)

Series (1์ฐจ์›)

  • ๊ฐœ๋…: ์—‘์…€์˜ โ€˜ํ•œ ์—ด(Column)โ€˜๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • ํŠน์ง•: ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ๋™์ผํ•œ ํƒ€์ž…(dtype)์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. (์˜ˆ: ๋ชจ๋‘ ์ •์ˆ˜, ๋ชจ๋‘ ๋‚ ์งœ)
  • ๊ตฌ์„ฑ: ๊ฐ’(Values) + ์ธ๋ฑ์Šค(Index)
import pandas as pd # Series ์ƒ์„ฑ price_series = df['sale_price'] print(f"ํƒ€์ž…: {type(price_series)}") print(f"๋ฐ์ดํ„ฐ ํƒ€์ž…(dtype): {price_series.dtype}") print(f"ํฌ๊ธฐ: {len(price_series):,}")
์‹คํ–‰ ๊ฒฐ๊ณผ
ํƒ€์ž…: <class 'pandas.core.series.Series'>
๋ฐ์ดํ„ฐ ํƒ€์ž…(dtype): float64
ํฌ๊ธฐ: 124,892

DataFrame (2์ฐจ์›)

  • ๊ฐœ๋…: ์—‘์…€์˜ โ€˜์‹œํŠธ(Sheet)โ€˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • ํŠน์ง•: ์—ฌ๋Ÿฌ ๊ฐœ์˜ Series๊ฐ€ ๋ชจ์—ฌ ์žˆ๋Š” ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.
  • Column-Major: ๊ฐ™์€ ์—ด(Column)๋ผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ์— ์—ฐ์†์ ์œผ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—ด ๋‹จ์œ„ ์—ฐ์‚ฐ์ด ๋น ๋ฆ…๋‹ˆ๋‹ค.
# DataFrame์˜ ๊ฐ ์ปฌ๋Ÿผ์€ Series print(f"df['category']์˜ ํƒ€์ž…: {type(df['category'])}") print(f"df[['category', 'sale_price']]์˜ ํƒ€์ž…: {type(df[['category', 'sale_price']])}")
์‹คํ–‰ ๊ฒฐ๊ณผ
df['category']์˜ ํƒ€์ž…: <class 'pandas.core.series.Series'>
df[['category', 'sale_price']]์˜ ํƒ€์ž…: <class 'pandas.core.frame.DataFrame'>

2. ๋ฒกํ„ฐํ™” ์—ฐ์‚ฐ (Vectorization)

Pandas(์™€ Numpy)์˜ ๊ฐ€์žฅ ํฐ ํŠน์ง•์€ Loop(for๋ฌธ)๋ฅผ ์“ฐ์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

โŒ ๋А๋ฆฐ ๋ฐฉ์‹ (Python for-loop)

# 100๋งŒ ๊ฐœ ๋ฐ์ดํ„ฐ ๊ธฐ์ค€ total = 0 for price in df['price']: total += price

ํŒŒ์ด์ฌ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๊ฐ€ ๋งค๋ฒˆ ๋ฆฌ์ŠคํŠธ ์›์†Œ๋ฅผ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด ํƒ€์ž…์„ ํ™•์ธํ•˜๊ณ  ๋”ํ•ฉ๋‹ˆ๋‹ค. (Overhead ํผ)

โœ… ๋น ๋ฅธ ๋ฐฉ์‹ (Vectorization)

total = df['price'].sum()

C์–ธ์–ด๋กœ ์ตœ์ ํ™”๋œ ๋‚ด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก ์ „์ฒด๋ฅผ ํ•œ ๋ฒˆ์—(CPU SIMD ๋ฐฉ์‹ ๋“ฑ) ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜๋ฐฑ ๋ฐฐ ๋น ๋ฆ…๋‹ˆ๋‹ค.

์‹คํ–‰ ๊ฒฐ๊ณผ (100๋งŒ ๊ฐœ ๊ธฐ์ค€)
For-loop Sum: 0.1892 sec
Vectorized Sum: 0.0004 sec
========================================
Speedup: 473x ๋น ๋ฆ„!

๋ฒกํ„ฐํ™” ์—ฐ์‚ฐ ์˜ˆ์‹œ

# ์ง‘๊ณ„ ์—ฐ์‚ฐ print(f"์ด ๋งค์ถœ: ${df['sale_price'].sum():,.2f}") print(f"ํ‰๊ท  ๋งค์ถœ: ${df['sale_price'].mean():.2f}") # ๋ฒกํ„ฐ ์‚ฐ์ˆ  ์—ฐ์‚ฐ df['profit'] = df['sale_price'] - df['cost'] df['margin_rate'] = (df['profit'] / df['sale_price'] * 100).round(2)
์‹คํ–‰ ๊ฒฐ๊ณผ
์ด ๋งค์ถœ: $5,234,892.45
ํ‰๊ท  ๋งค์ถœ: $41.92

3. ์ธ๋ฑ์‹ฑ (Indexing: loc vs iloc)

๊ฐ€์žฅ ํ—ท๊ฐˆ๋ฆฌ๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ๋ถ„๋ฌธ๋ฒ•์„ค๋ช…์˜ˆ์‹œ
Label ๊ธฐ๋ฐ˜loc[ํ–‰์ด๋ฆ„, ์—ด์ด๋ฆ„]์ด๋ฆ„์œผ๋กœ ์ฐพ์Šต๋‹ˆ๋‹ค.df.loc[0, 'category']
Position ๊ธฐ๋ฐ˜iloc[ํ–‰๋ฒˆํ˜ธ, ์—ด๋ฒˆํ˜ธ]**์ˆซ์ž(์ˆœ์„œ)**๋กœ ์ฐพ์Šต๋‹ˆ๋‹ค.df.iloc[0, 3] (0๋ฒˆ์งธ ํ–‰, 3๋ฒˆ์งธ ์—ด)
# loc: Label ๊ธฐ๋ฐ˜ (์ด๋ฆ„์œผ๋กœ) sample.loc[0, 'category'] # 'Jeans' # iloc: Position ๊ธฐ๋ฐ˜ (์ˆœ์„œ๋กœ) sample.iloc[0, 1] # 'Jeans' # ์ฃผ์˜: loc์€ ๋ ํฌํ•จ, iloc์€ ๋ ๋ฏธํฌํ•จ sample.loc[0:2] # 0, 1, 2 (3๊ฐœ) sample.iloc[0:2] # 0, 1 (2๊ฐœ)

์กฐ๊ฑด๋ถ€ ํ•„ํ„ฐ๋ง

# Boolean Indexing (๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ) high_value = df[df['sale_price'] > 100] # ๋ณตํ•ฉ ์กฐ๊ฑด filtered = df[(df['sale_price'] > 50) & (df['category'] == 'Jeans')] # query() ๋ฉ”์„œ๋“œ (SQL ์Šคํƒ€์ผ) filtered_query = df.query("sale_price > 50 and category == 'Jeans'")

Best Practice: ๊ฐ€๋Šฅํ•˜๋ฉด ๋ช…์‹œ์ ์ธ loc๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, query() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋…์„ฑ์— ์ข‹์Šต๋‹ˆ๋‹ค.


์ปค๋ฆฌํ˜๋Ÿผ (Curriculum)

1. ๋ฐ์ดํ„ฐ ๋กœ๋“œ์™€ ํƒ์ƒ‰

CSV, Excel, JSON ๋“ฑ ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ๊ธฐ๋ณธ์ ์ธ ํƒ์ƒ‰ ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

2. ๋ฐ์ดํ„ฐ ์ •์ œ

๊ฒฐ์ธก์น˜ ์ฒ˜๋ฆฌ, ์ค‘๋ณต ์ œ๊ฑฐ, ์ด์ƒ์น˜ ํƒ์ง€ ๋“ฑ ๋ฐ์ดํ„ฐ ํ’ˆ์งˆ ๊ด€๋ฆฌ ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

3. ๊ณ ๊ธ‰ ํ•„ํ„ฐ๋ง

๋‹ค์–‘ํ•œ ์กฐ๊ฑด์„ ํ™œ์šฉํ•œ ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง ๊ธฐ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

4. ๊ทธ๋ฃนํ™”์™€ ์ง‘๊ณ„

groupby()์™€ ์ง‘๊ณ„ ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•œ ๋ฐ์ดํ„ฐ ์š”์•ฝ ๋ฐ ๋ถ„์„ ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

5. ๋ฐ์ดํ„ฐ ๋ณ‘ํ•ฉ

์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์„ ๊ฒฐํ•ฉํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

6. ๋‚ ์งœ/์‹œ๊ฐ„ ์ฒ˜๋ฆฌ

์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ datetime ํƒ€์ž… ํ™œ์šฉ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

7. ํ”ผ๋ฒ—๊ณผ ์žฌ๊ตฌ์กฐํ™”

๋ฐ์ดํ„ฐ์˜ ํ˜•ํƒœ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ํ”ผ๋ฒ—, ๋ฉœํŠธ, ์Šคํƒ ์—ฐ์‚ฐ์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

SQL โ†” Pandas ๋ณ€ํ™˜ ๊ฐ€์ด๋“œ

SQLPandas
SELECT col1, col2df[['col1', 'col2']]
WHERE conditiondf.query("condition") ๋˜๋Š” df[condition]
GROUP BY coldf.groupby('col')
JOINdf.merge(df2, on='key')
ORDER BY coldf.sort_values('col')
LIMIT ndf.head(n)
# SQL: SELECT category, SUM(sale_price) # FROM df # GROUP BY category # ORDER BY SUM(sale_price) DESC # LIMIT 5 result = ( df.groupby('category')['sale_price'] .sum() .sort_values(ascending=False) .head(5) )
์‹คํ–‰ ๊ฒฐ๊ณผ
category
Outerwear & Coats    892341.23
Jeans                654892.11
Sweaters             543210.87
Suits & Sport Coats  432109.65
Swim                 321098.43
Name: sale_price, dtype: float64

ํ•ต์‹ฌ ์ •๋ฆฌ

  1. Series: 1์ฐจ์› ๋ฐฐ์—ด (์—‘์…€ ํ•œ ์—ด), ๋™์ผ ํƒ€์ž…
  2. DataFrame: 2์ฐจ์› ํ…Œ์ด๋ธ” (์—‘์…€ ์‹œํŠธ), ์—ฌ๋Ÿฌ Series์˜ ์กฐํ•ฉ
  3. ๋ฒกํ„ฐํ™”: for-loop ๋Œ€์‹  ๋‚ด์žฅ ํ•จ์ˆ˜ ์‚ฌ์šฉ โ†’ 100~1000๋ฐฐ ์„ฑ๋Šฅ ํ–ฅ์ƒ
  4. loc: Label(์ด๋ฆ„) ๊ธฐ๋ฐ˜, ๋ ํฌํ•จ
  5. iloc: Position(์ˆซ์ž) ๊ธฐ๋ฐ˜, ๋ ๋ฏธํฌํ•จ
๐Ÿ’ก
๋‹ค์Œ ๋‹จ๊ณ„

์ด ๊ฐœ๋…๋“ค์„ ์ง์ ‘ ์‹ค์Šตํ•˜๋ ค๋ฉด ์ปค๋ฆฌํ˜๋Ÿผ์˜ ๊ฐ ์„น์…˜์œผ๋กœ ์ด๋™ํ•˜์—ฌ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ๋”ฐ๋ผํ•ด๋ณด์„ธ์š”!

Last updated on

๐Ÿค–AI Mock InterviewPractice with real questions