Pandas (Python Data Analysis)
Python ์ํ๊ณ์์ ๋ฐ์ดํฐ ๋ถ์์ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Pandas์ ํต์ฌ ๊ฐ๋ ๊ณผ ์๋ฆฌ๋ฅผ ๋ค๋ฃน๋๋ค.
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 ๋ฐฉ์ ๋ฑ) ์ฒ๋ฆฌํฉ๋๋ค. ์๋ฐฑ ๋ฐฐ ๋น ๋ฆ ๋๋ค.
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 ๋ณํ ๊ฐ์ด๋
| SQL | Pandas |
|---|---|
SELECT col1, col2 | df[['col1', 'col2']] |
WHERE condition | df.query("condition") ๋๋ df[condition] |
GROUP BY col | df.groupby('col') |
JOIN | df.merge(df2, on='key') |
ORDER BY col | df.sort_values('col') |
LIMIT n | df.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
ํต์ฌ ์ ๋ฆฌ
- Series: 1์ฐจ์ ๋ฐฐ์ด (์์ ํ ์ด), ๋์ผ ํ์
- DataFrame: 2์ฐจ์ ํ ์ด๋ธ (์์ ์ํธ), ์ฌ๋ฌ Series์ ์กฐํฉ
- ๋ฒกํฐํ: for-loop ๋์ ๋ด์ฅ ํจ์ ์ฌ์ฉ โ 100~1000๋ฐฐ ์ฑ๋ฅ ํฅ์
- loc: Label(์ด๋ฆ) ๊ธฐ๋ฐ, ๋ ํฌํจ
- iloc: Position(์ซ์) ๊ธฐ๋ฐ, ๋ ๋ฏธํฌํจ
์ด ๊ฐ๋ ๋ค์ ์ง์ ์ค์ตํ๋ ค๋ฉด ์ปค๋ฆฌํ๋ผ์ ๊ฐ ์น์ ์ผ๋ก ์ด๋ํ์ฌ ์์ ์ฝ๋๋ฅผ ๋ฐ๋ผํด๋ณด์ธ์!