KR_Metplotlib - somaz94/python-study GitHub Wiki
๋ฐ์ดํฐ๋ฅผ ์๊ฐ์ ์ผ๋ก ํํํ๊ธฐ ์ํ ๊ธฐ๋ณธ ๊ทธ๋ํ ์์ฑ ๋ฐฉ๋ฒ์ด๋ค.
import matplotlib.pyplot as plt
import numpy as np
from typing import Tuple, List, Optional, Union
def create_sine_plot(
x_range: Tuple[float, float] = (0, 10),
num_points: int = 100,
color: str = 'b-',
title: str = '๊ธฐ๋ณธ ์ฌ์ธ ๊ทธ๋ํ',
figsize: Tuple[int, int] = (10, 6)
) -> None:
"""์ฌ์ธ ํจ์์ ๊ทธ๋ํ๋ฅผ ์์ฑํ๊ณ ํ์ํ๋ ํจ์
Args:
x_range: x์ถ ๋ฒ์ (์์, ๋)
num_points: ๋ฐ์ดํฐ ํฌ์ธํธ ์
color: ์ ์์ ๋ฐ ์คํ์ผ
title: ๊ทธ๋ํ ์ ๋ชฉ
figsize: ๊ทธ๋ํ ํฌ๊ธฐ (๊ฐ๋ก, ์ธ๋ก) ์ธ์น ๋จ์
"""
# ๋ฐ์ดํฐ ์์ฑ
x = np.linspace(x_range[0], x_range[1], num_points)
y = np.sin(x)
# ๊ทธ๋ํ ์์ฑ
plt.figure(figsize=figsize)
plt.plot(x, y, color, label='sin(x)')
plt.title(title)
plt.xlabel('x ์ถ')
plt.ylabel('y ์ถ')
plt.legend()
plt.grid(True)
plt.show()
# ๊ธฐ๋ณธ ์ฌ์ฉ ์์
create_sine_plot()
# ์ฌ์ฉ์ ์ ์ ์ค์ ์์
create_sine_plot(
x_range=(-5, 5),
num_points=200,
color='r--',
title='์ฌ์ฉ์ ์ ์ ์ฌ์ธ ๊ทธ๋ํ',
figsize=(12, 8)
)
# ์ง์ ๊ทธ๋ํ ๊ทธ๋ฆฌ๊ธฐ
x = np.linspace(0, 10, 100)
y = np.sin(x)
y2 = np.cos(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y, 'b-', label='sin(x)')
plt.plot(x, y2, 'r--', label='cos(x)')
plt.title('์ฌ์ธ๊ณผ ์ฝ์ฌ์ธ ๊ทธ๋ํ')
plt.xlabel('x ์ถ')
plt.ylabel('y ์ถ')
plt.legend()
plt.grid(True)
plt.savefig('sine_cosine.png', dpi=300) # ๊ณ ํด์๋๋ก ์ ์ฅ
plt.show()
โ
ํน์ง:
- ๊ทธ๋ํ ํฌ๊ธฐ ์ค์
- ์ถ ๋ ์ด๋ธ ์ง์
- ๋ฒ๋ก ์ถ๊ฐ
- ๊ฒฉ์์ ํ์
- ํ์ผ๋ก ์ ์ฅ
- ํจ์ํ๋ ์ ๊ทผ๋ฒ
Matplotlib์ ๊ธฐ๋ณธ ๊ทธ๋ํ ์์๋ค์ด๋ค.
- Figure: ์ ์ฒด ๊ทธ๋ํ ์ปจํ ์ด๋
- Axes: ์ค์ ๋ฐ์ดํฐ๊ฐ ํ์๋๋ ์์ญ
- Axis: ์ถ ์ ๋ณด์ ๋๊ธ์ ๋ด๋น
- Line: ์ ๋ฐ์ดํฐ๋ฅผ ํํ
- Marker: ๋ฐ์ดํฐ ํฌ์ธํธ๋ฅผ ๊ฐ์กฐํ๋ ๊ธฐํธ
- Legend: ๊ทธ๋ํ ์์๋ฅผ ์ค๋ช ํ๋ ๋ฒ๋ก
- Title: ๊ทธ๋ํ ์ ๋ชฉ
- Grid: ๋ฐ์ดํฐ ํ๋ ์ ๋๋ ๊ฒฉ์์
๋ค์ํ ์ข
๋ฅ์ ๊ทธ๋ํ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์๊ฐํํ๋ ๋ฐฉ๋ฒ์ด๋ค.
import matplotlib.pyplot as plt
import numpy as np
from typing import List, Tuple, Dict, Optional, Union, Any
class PlotGenerator:
"""๋ค์ํ ๊ทธ๋ํ ์์ฑ์ ์ํ ํด๋์ค"""
def __init__(self, style: str = 'default'):
"""์ด๊ธฐํ ํจ์
Args:
style: ์ ์ฉํ matplotlib ์คํ์ผ
"""
if style != 'default':
plt.style.use(style)
def scatter_plot(
self,
x: np.ndarray,
y: np.ndarray,
figsize: Tuple[int, int] = (10, 6),
color: Union[str, np.ndarray] = 'blue',
alpha: float = 0.5,
title: str = '์ฐ์ ๋',
save_path: Optional[str] = None
) -> None:
"""์ฐ์ ๋ ๊ทธ๋ํ ์์ฑ
Args:
x: x ์ขํ ๋ฐ์ดํฐ
y: y ์ขํ ๋ฐ์ดํฐ
figsize: ๊ทธ๋ํ ํฌ๊ธฐ
color: ์ ์ ์์
alpha: ํฌ๋ช
๋ (0~1)
title: ๊ทธ๋ํ ์ ๋ชฉ
save_path: ์ ์ฅํ ํ์ผ ๊ฒฝ๋ก
"""
plt.figure(figsize=figsize)
plt.scatter(x, y, c=color, alpha=alpha)
plt.title(title)
plt.grid(True, linestyle='--', alpha=0.7)
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
plt.show()
def bar_plot(
self,
categories: List[str],
values: List[float],
figsize: Tuple[int, int] = (8, 6),
color: Union[str, List[str]] = 'skyblue',
title: str = '๋ง๋ ๊ทธ๋ํ',
save_path: Optional[str] = None
) -> None:
"""๋ง๋ ๊ทธ๋ํ ์์ฑ
Args:
categories: ๋ฒ์ฃผ ๋ ์ด๋ธ
values: ๊ฐ ๋ฒ์ฃผ๋ณ ๊ฐ
figsize: ๊ทธ๋ํ ํฌ๊ธฐ
color: ๋ง๋ ์์
title: ๊ทธ๋ํ ์ ๋ชฉ
save_path: ์ ์ฅํ ํ์ผ ๊ฒฝ๋ก
"""
plt.figure(figsize=figsize)
bars = plt.bar(categories, values, color=color)
# ๋ง๋ ์์ ๊ฐ ํ์
for bar in bars:
height = bar.get_height()
plt.text(
bar.get_x() + bar.get_width()/2.,
height,
f'{height:.1f}',
ha='center', va='bottom'
)
plt.title(title)
plt.grid(True, axis='y', linestyle='--', alpha=0.7)
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
plt.show()
def histogram(
self,
data: np.ndarray,
bins: int = 30,
figsize: Tuple[int, int] = (10, 6),
color: str = 'skyblue',
title: str = 'ํ์คํ ๊ทธ๋จ',
save_path: Optional[str] = None
) -> None:
"""ํ์คํ ๊ทธ๋จ ์์ฑ
Args:
data: ๋ฐ์ดํฐ ๋ฐฐ์ด
bins: ๊ตฌ๊ฐ ์
figsize: ๊ทธ๋ํ ํฌ๊ธฐ
color: ํ์คํ ๊ทธ๋จ ์์
title: ๊ทธ๋ํ ์ ๋ชฉ
save_path: ์ ์ฅํ ํ์ผ ๊ฒฝ๋ก
"""
plt.figure(figsize=figsize)
plt.hist(data, bins=bins, color=color, edgecolor='black', alpha=0.7)
plt.title(title)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xlabel('๊ฐ')
plt.ylabel('๋น๋')
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
plt.show()
def pie_chart(
self,
sizes: List[float],
labels: List[str],
figsize: Tuple[int, int] = (8, 8),
colors: Optional[List[str]] = None,
explode: Optional[List[float]] = None,
title: str = 'ํ์ด ์ฐจํธ',
save_path: Optional[str] = None
) -> None:
"""ํ์ด ์ฐจํธ ์์ฑ
Args:
sizes: ๊ฐ ์กฐ๊ฐ์ ํฌ๊ธฐ
labels: ๊ฐ ์กฐ๊ฐ์ ๋ ์ด๋ธ
figsize: ๊ทธ๋ํ ํฌ๊ธฐ
colors: ๊ฐ ์กฐ๊ฐ์ ์์
explode: ํน์ ์กฐ๊ฐ์ ๋ถ๋ฆฌํ๊ธฐ ์ํ ๊ฐ (์: [0, 0.1, 0])
title: ๊ทธ๋ํ ์ ๋ชฉ
save_path: ์ ์ฅํ ํ์ผ ๊ฒฝ๋ก
"""
plt.figure(figsize=figsize)
plt.pie(
sizes,
labels=labels,
colors=colors,
explode=explode,
autopct='%1.1f%%',
shadow=True,
startangle=90
)
plt.axis('equal') # ์ํ ์ ์ง
plt.title(title)
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
plt.show()
# ์ฌ์ฉ ์์
plot_gen = PlotGenerator(style='seaborn-v0_8-whitegrid')
# ์ฐ์ ๋ ์์
x = np.random.randn(100)
y = np.random.randn(100)
plot_gen.scatter_plot(x, y, title='๋๋ค ๋ถํฌ ์ฐ์ ๋')
# ๋ง๋ ๊ทธ๋ํ ์์
categories = ['A', 'B', 'C', 'D']
values = [4, 7, 2, 5]
plot_gen.bar_plot(categories, values, color=['red', 'green', 'blue', 'orange'])
# ํ์คํ ๊ทธ๋จ ์์
data = np.random.normal(0, 1, 1000)
plot_gen.histogram(data, bins=30, title='์ ๊ท ๋ถํฌ ํ์คํ ๊ทธ๋จ')
# ํ์ด ์ฐจํธ ์์
sizes = [35, 30, 20, 15]
labels = ['A', 'B', 'C', 'D']
explode = [0, 0.1, 0, 0] # B ์กฐ๊ฐ๋ง ๋ถ๋ฆฌ
plot_gen.pie_chart(sizes, labels, explode=explode, title='์นดํ
๊ณ ๋ฆฌ ๋ถํฌ')
โ
ํน์ง:
- ๋ค์ํ ๊ทธ๋ํ ์ ํ
- ํฌ๋ช ๋ ์กฐ์
- ๋ฐ์ดํฐ ์๊ฐํ
- ๊ฐ์ฒด ์งํฅ์ ์ ๊ทผ๋ฒ
- ์ฌ์ฉ์ ์ ์ ์ต์
- ์ ์ฅ ๊ธฐ๋ฅ ํตํฉ
๊ทธ๋ํ์ ์๊ฐ์ ํํ์ ํฅ์์ํค๋ ์คํ์ผ๊ณผ ์์ ์ค์ ๋ฐฉ๋ฒ์ด๋ค.
import matplotlib.pyplot as plt
import numpy as np
from typing import Optional, Tuple, List, Dict, Any
import matplotlib.cm as cm
def apply_style_demo(style_name: str = 'default') -> None:
"""๋ค์ํ ์คํ์ผ ์ ์ฉ ๋ฐ๋ชจ
Args:
style_name: ์ ์ฉํ matplotlib ์คํ์ผ
"""
if style_name != 'default':
plt.style.use(style_name)
# ๋ฐ์ดํฐ ์์ฑ
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
# ๊ทธ๋ํ ์์ฑ
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x, y1, label='sin(x)')
ax.plot(x, y2, label='cos(x)')
ax.set_title(f'์คํ์ผ: {style_name}')
ax.set_xlabel('x ์ถ')
ax.set_ylabel('y ์ถ')
ax.legend()
ax.grid(True)
plt.show()
# ์ปฌ๋ฌ๋งต ๋ฐ๋ชจ ํจ์
def colormap_demo(cmap_name: str = 'viridis') -> None:
"""๋ค์ํ ์ปฌ๋ฌ๋งต ์ฌ์ฉ ๋ฐ๋ชจ
Args:
cmap_name: ์ฌ์ฉํ ์ปฌ๋ฌ๋งต ์ด๋ฆ
"""
# ๋ฐ์ดํฐ ์์ฑ
x = np.random.randn(1000)
y = np.random.randn(1000)
colors = np.random.rand(1000)
fig, ax = plt.subplots(figsize=(10, 6))
scatter = ax.scatter(x, y, c=colors, cmap=cmap_name, s=50, alpha=0.7)
# ์ปฌ๋ฌ๋ฐ ์ถ๊ฐ
cbar = plt.colorbar(scatter)
cbar.set_label('๊ฐ')
ax.set_title(f'์ปฌ๋ฌ๋งต: {cmap_name}')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.grid(True, linestyle='--', alpha=0.7)
plt.show()
# ์ฌ์ฉ ๊ฐ๋ฅํ ์คํ์ผ ์ถ๋ ฅ
available_styles = plt.style.available
print(f"์ฌ์ฉ ๊ฐ๋ฅํ ์คํ์ผ: {len(available_styles)}๊ฐ")
print(available_styles[:5]) # ์ฒ์ 5๊ฐ๋ง ์ถ๋ ฅ
# ๋ช ๊ฐ์ง ์คํ์ผ ๋ฐ๋ชจ
for style in ['default', 'seaborn-v0_8-darkgrid', 'ggplot', 'bmh']:
apply_style_demo(style)
# ์ปฌ๋ฌ๋งต ๋ฐ๋ชจ
for cmap in ['viridis', 'plasma', 'inferno', 'cividis', 'coolwarm']:
colormap_demo(cmap)
# ์ฌ์ฉ์ ์ ์ ์์ ํ๋ ํธ
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(10, 6))
# ์ฌ์ฉ์ ์ ์ ์์ ์ค์
colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd']
for i, alpha in enumerate([0.2, 0.4, 0.6, 0.8, 1.0]):
ax.plot(x, np.sin(x + i*0.5), color=colors[i],
linewidth=2, alpha=alpha,
label=f'sin(x + {i*0.5:.1f})')
ax.set_title('์ฌ์ฉ์ ์ ์ ์์ ํ๋ ํธ')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.legend()
ax.grid(True)
plt.show()
โ
ํน์ง:
- ์คํ์ผ ํ ๋ง
- ์ปฌ๋ฌ๋งต ํ์ฉ
- ์๊ฐ์ ํจ๊ณผ
- ์ผ๊ด๋ ์๊ฐํ
- ํฌ๋ช ๋ ์กฐ์
- ์ฌ์ฉ์ ์ ์ ์์
Matplotlib์์ ์์ฃผ ์ฌ์ฉ๋๋ ์คํ์ผ๊ณผ ์ปฌ๋ฌ๋งต์ด๋ค.
์ธ๊ธฐ ์๋ ์คํ์ผ:
- seaborn-v0_8: ๊น๋ํ๊ณ ํ๋์ ์ธ ํต๊ณ ์๊ฐํ ์คํ์ผ
- ggplot: R์ ggplot2์ ์ ์ฌํ ์คํ์ผ
- bmh: Bayesian Methods for Hackers ์ฑ ์ ์คํ์ผ
- fivethirtyeight: FiveThirtyEight ์น์ฌ์ดํธ์ ์ ์ฌํ ์คํ์ผ
- dark_background: ์ด๋์ด ๋ฐฐ๊ฒฝ์ ์คํ์ผ
์ ์ฉํ ์ปฌ๋ฌ๋งต:
- viridis: ์ฐ์์ ์ธ ๋ฐ์ดํฐ์ ์ต์ ํ๋ ์ปฌ๋ฌ๋งต (์์ฝ ์นํ์ )
- plasma: ๋์ ๋๋น์ ์ปฌ๋ฌ๋งต
- coolwarm: ์๊ทน ๋ฐ์ดํฐ ํํ์ ์ ํฉํ ์ปฌ๋ฌ๋งต
- jet: ๊ณ ์ ์ ์ธ ๋ฌด์ง๊ฐ ์ปฌ๋ฌ๋งต (ํน์ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉ ๊ถ์ฅ)
- Paired: ๋ฒ์ฃผํ ๋ฐ์ดํฐ์ ์ ํฉํ ์ปฌ๋ฌ๋งต
์ฌ๋ฌ ๊ทธ๋ํ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋ฐฐ์นํ๋ ์๋ธํ๋กฏ๊ณผ ๋ ์ด์์ ๊ด๋ฆฌ ๋ฐฉ๋ฒ์ด๋ค.
import matplotlib.pyplot as plt
import numpy as np
from typing import Tuple, List, Dict, Optional, Union
import matplotlib.gridspec as gridspec
class MultiplotManager:
"""์ฌ๋ฌ ๊ทธ๋ํ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ํด๋์ค"""
def __init__(self, style: str = 'default'):
"""์ด๊ธฐํ ํจ์
Args:
style: ์ ์ฉํ matplotlib ์คํ์ผ
"""
if style != 'default':
plt.style.use(style)
def create_basic_grid(
self,
rows: int,
cols: int,
figsize: Tuple[int, int] = (12, 10),
title: Optional[str] = None
) -> Tuple[plt.Figure, np.ndarray]:
"""๊ธฐ๋ณธ ๊ทธ๋ฆฌ๋ ๋ ์ด์์ ์์ฑ
Args:
rows: ํ ์
cols: ์ด ์
figsize: ์ ์ฒด ๊ทธ๋ฆผ ํฌ๊ธฐ
title: ์ ์ฒด ๊ทธ๋ฆผ ์ ๋ชฉ
Returns:
ํํ(Figure, Axes ๋ฐฐ์ด)
"""
fig, axes = plt.subplots(rows, cols, figsize=figsize)
if title:
fig.suptitle(title, fontsize=16)
# ๋จ์ผ Axes์ธ ๊ฒฝ์ฐ ๋ฐฐ์ด๋ก ๋ณํ
if rows == 1 and cols == 1:
axes = np.array([[axes]])
elif rows == 1:
axes = axes.reshape(1, cols)
elif cols == 1:
axes = axes.reshape(rows, 1)
return fig, axes
def create_complex_grid(
self,
layout: List[Dict[str, Union[int, Tuple[int, int, int, int]]]],
figsize: Tuple[int, int] = (12, 10),
title: Optional[str] = None
) -> Tuple[plt.Figure, Dict[str, plt.Axes]]:
"""๋ณต์กํ ๊ทธ๋ฆฌ๋ ๋ ์ด์์ ์์ฑ
Args:
layout: ๋ ์ด์์ ์ ์ (๊ฐ ์์๋ name๊ณผ position์ ํฌํจ)
figsize: ์ ์ฒด ๊ทธ๋ฆผ ํฌ๊ธฐ
title: ์ ์ฒด ๊ทธ๋ฆผ ์ ๋ชฉ
Returns:
ํํ(Figure, ์ด๋ฆ-Axes ์ฌ์ )
"""
fig = plt.figure(figsize=figsize)
if title:
fig.suptitle(title, fontsize=16)
gs = gridspec.GridSpec(12, 12) # 12x12 ๊ทธ๋ฆฌ๋ ์ฌ์ฉ
axes_dict = {}
for item in layout:
name = item['name']
pos = item['position'] # (row_start, row_end, col_start, col_end)
axes_dict[name] = fig.add_subplot(
gs[pos[0]:pos[1], pos[2]:pos[3]]
)
return fig, axes_dict
def example_basic_grid(self) -> None:
"""๊ธฐ๋ณธ ๊ทธ๋ฆฌ๋ ์์"""
# ๋ฐ์ดํฐ ์ค๋น
x = np.linspace(0, 10, 100)
categories = ['A', 'B', 'C', 'D']
values = [4, 7, 2, 5]
random_data = np.random.randn(1000)
# 2x2 ๊ทธ๋ฆฌ๋ ์์ฑ
fig, axes = self.create_basic_grid(2, 2, title="๊ธฐ๋ณธ ์๋ธํ๋กฏ ๊ทธ๋ฆฌ๋")
# ์ฒซ ๋ฒ์งธ ๊ทธ๋ํ: ์ ๊ทธ๋ํ
axes[0, 0].plot(x, np.sin(x))
axes[0, 0].set_title('์ฌ์ธ ํจ์')
axes[0, 0].grid(True)
# ๋ ๋ฒ์งธ ๊ทธ๋ํ: ์ฐ์ ๋
scatter_x = np.random.randn(30)
scatter_y = np.random.randn(30)
axes[0, 1].scatter(scatter_x, scatter_y)
axes[0, 1].set_title('์ฐ์ ๋')
axes[0, 1].grid(True)
# ์ธ ๋ฒ์งธ ๊ทธ๋ํ: ๋ง๋ ๊ทธ๋ํ
axes[1, 0].bar(categories, values)
axes[1, 0].set_title('๋ง๋ ๊ทธ๋ํ')
# ๋ค ๋ฒ์งธ ๊ทธ๋ํ: ํ์คํ ๊ทธ๋จ
axes[1, 1].hist(random_data, bins=30)
axes[1, 1].set_title('ํ์คํ ๊ทธ๋จ')
plt.tight_layout()
plt.show()
def example_complex_grid(self) -> None:
"""๋ณต์กํ ๊ทธ๋ฆฌ๋ ์์"""
# ๋ ์ด์์ ์ ์
layout = [
{'name': 'main', 'position': (0, 8, 0, 8)}, # ํฐ ๋ฉ์ธ ํ๋กฏ
{'name': 'right_top', 'position': (0, 4, 8, 12)}, # ์ค๋ฅธ์ชฝ ์๋จ
{'name': 'right_bottom', 'position': (4, 8, 8, 12)}, # ์ค๋ฅธ์ชฝ ํ๋จ
{'name': 'bottom', 'position': (8, 12, 0, 12)} # ํ๋จ ์ ์ฒด
]
fig, axes = self.create_complex_grid(layout, title="๋ณต์กํ ๋ ์ด์์ ์์")
# ๋ฐ์ดํฐ ์ค๋น
x = np.linspace(0, 10, 100)
t = np.linspace(0, 1, 100)
# ๋ฉ์ธ ํ๋กฏ: 2D ์ปฌ๋ฌ๋งต
X, Y = np.meshgrid(x, x)
Z = np.sin(X) * np.cos(Y)
main = axes['main'].contourf(X, Y, Z, cmap='viridis')
axes['main'].set_title('2D ์ปฌ๋ฌ๋งต')
plt.colorbar(main, ax=axes['main'])
# ์ค๋ฅธ์ชฝ ์๋จ: ์ ๊ทธ๋ํ
axes['right_top'].plot(x, np.sin(x), 'r-')
axes['right_top'].set_title('์ฌ์ธ ํจ์')
# ์ค๋ฅธ์ชฝ ํ๋จ: ์ฐ์ ๋
scatter_x = np.random.randn(50)
scatter_y = np.random.randn(50)
axes['right_bottom'].scatter(scatter_x, scatter_y)
axes['right_bottom'].set_title('์ฐ์ ๋')
# ํ๋จ: ์ฌ๋ฌ ์ ๊ทธ๋ํ
for i, freq in enumerate([1, 2, 3, 4]):
axes['bottom'].plot(t, np.sin(2*np.pi*freq*t),
label=f'f={freq} Hz')
axes['bottom'].set_title('๋ค์ํ ์ฃผํ์')
axes['bottom'].legend()
plt.tight_layout()
plt.show()
# ์ฌ์ฉ ์์
manager = MultiplotManager(style='seaborn-v0_8-whitegrid')
manager.example_basic_grid()
manager.example_complex_grid()
โ
ํน์ง:
- ๋ค์ค ๊ทธ๋ํ
- ๋ ์ด์์ ์กฐ์
- ๊ทธ๋ํ ๋ฐฐ์น
- ๊ทธ๋ฆฌ๋ ์คํ ํ์ฉ
- ๋ณต์กํ ๋ ์ด์์ ์์ฑ
- ๊ฐ์ฒด ์งํฅ์ ์ ๊ทผ
Matplotlib์ ๊ณ ๊ธ ๊ธฐ๋ฅ๊ณผ 3D ์๊ฐํ ๋ฐฉ๋ฒ์ด๋ค.
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.animation import FuncAnimation
import matplotlib.patches as patches
from typing import Tuple, List, Dict, Optional, Callable, Any, Union
class AdvancedPlotting:
"""Matplotlib์ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ํ์ฉํ๋ ํด๋์ค"""
def plot_3d_surface(
self,
x_range: Tuple[float, float] = (-5, 5),
y_range: Tuple[float, float] = (-5, 5),
grid_size: int = 100,
func: Callable[[np.ndarray, np.ndarray], np.ndarray] = None,
cmap: str = 'viridis',
figsize: Tuple[int, int] = (10, 7),
view_angle: Tuple[float, float] = (30, 45)
) -> None:
"""3D ํ๋ฉด ํ๋กฏ ์์ฑ
Args:
x_range: x์ถ ๋ฒ์
y_range: y์ถ ๋ฒ์
grid_size: ๊ทธ๋ฆฌ๋ ํฌ๊ธฐ
func: ํ๋ฉด์ ์ ์ํ๋ ํจ์, ๊ธฐ๋ณธ๊ฐ์ sin(sqrt(x^2+y^2))
cmap: ์ปฌ๋ฌ๋งต
figsize: ๊ทธ๋ํ ํฌ๊ธฐ
view_angle: ์์ผ๊ฐ (elevation, azimuth)
"""
if func is None:
func = lambda x, y: np.sin(np.sqrt(x**2 + y**2))
# ๋ฐ์ดํฐ ์์ฑ
x = np.linspace(x_range[0], x_range[1], grid_size)
y = np.linspace(y_range[0], y_range[1], grid_size)
X, Y = np.meshgrid(x, y)
Z = func(X, Y)
# 3D ํ๋กฏ ์์ฑ
fig = plt.figure(figsize=figsize)
ax = fig.add_subplot(111, projection='3d')
# ์ํผ์ค ํ๋กฏ
surface = ax.plot_surface(X, Y, Z, cmap=cmap,
edgecolor='none', alpha=0.8)
# ๋ฑ๊ณ ์ ์ถ๊ฐ
ax.contour(X, Y, Z, zdir='z', offset=Z.min(), cmap='coolwarm')
# ์์ผ๊ฐ ์ค์
ax.view_init(elev=view_angle[0], azim=view_angle[1])
# ์ ๋ชฉ๊ณผ ๋ ์ด๋ธ
ax.set_title('3D ํ๋ฉด ํ๋กฏ', fontsize=14)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# ์ปฌ๋ฌ๋ฐ ์ถ๊ฐ
fig.colorbar(surface, ax=ax, shrink=0.5, aspect=5)
plt.show()
def create_animation(
self,
frames: int = 100,
interval: int = 50,
figsize: Tuple[int, int] = (8, 6),
save_path: Optional[str] = None
) -> None:
"""์ ๋๋ฉ์ด์
์์ฑ
Args:
frames: ํ๋ ์ ์
interval: ํ๋ ์ ๊ฐ ๊ฐ๊ฒฉ(๋ฐ๋ฆฌ์ด)
figsize: ๊ทธ๋ํ ํฌ๊ธฐ
save_path: ์ ์ฅ ๊ฒฝ๋ก
"""
fig, ax = plt.subplots(figsize=figsize)
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1.5, 1.5)
line, = ax.plot([], [], lw=2)
ax.grid(True)
# ์ด๊ธฐํ ํจ์
def init():
line.set_data([], [])
return line,
# ์ ๋๋ฉ์ด์
ํ๋ ์ ์
๋ฐ์ดํธ ํจ์
def animate(i):
x = np.linspace(0, 2*np.pi, 1000)
phase = 2*np.pi * i / frames
y = np.sin(x + phase)
line.set_data(x, y)
ax.set_title(f'์ฌ์ธ ํ๋ (์์: {phase:.2f} ๋ผ๋์)')
return line,
# ์ ๋๋ฉ์ด์
์์ฑ
anim = FuncAnimation(fig, animate, init_func=init,
frames=frames, interval=interval, blit=True)
# ์ ์ฅ
if save_path:
anim.save(save_path, writer='pillow', fps=30)
plt.show()
def custom_plot_with_annotations(
self,
figsize: Tuple[int, int] = (10, 6)
) -> None:
"""์ฃผ์๊ณผ ์ฌ์ฉ์ ์ ์ ์์๊ฐ ์๋ ํ๋กฏ
Args:
figsize: ๊ทธ๋ํ ํฌ๊ธฐ
"""
fig, ax = plt.subplots(figsize=figsize)
# ๋ฐ์ดํฐ ์์ฑ
x = np.linspace(0, 10, 100)
y = np.sin(x)
# ๊ธฐ๋ณธ ํ๋กฏ
ax.plot(x, y, 'b-', lw=2)
# ํน์ ์ง์ ๊ฐ์กฐ
max_point_idx = np.argmax(y)
min_point_idx = np.argmin(y)
# ํน์ ์ง์ ์ ๋ง์ปค ์ถ๊ฐ
ax.plot(x[max_point_idx], y[max_point_idx], 'ro', ms=10)
ax.plot(x[min_point_idx], y[min_point_idx], 'go', ms=10)
# ํ
์คํธ ์ฃผ์ ์ถ๊ฐ
ax.annotate('์ต๋๊ฐ', xy=(x[max_point_idx], y[max_point_idx]),
xytext=(x[max_point_idx]+0.5, y[max_point_idx]+0.3),
arrowprops=dict(facecolor='red', shrink=0.05))
ax.annotate('์ต์๊ฐ', xy=(x[min_point_idx], y[min_point_idx]),
xytext=(x[min_point_idx]+0.5, y[min_point_idx]-0.3),
arrowprops=dict(facecolor='green', shrink=0.05))
# ์์ญ ๊ฐ์กฐ
ax.axvspan(2, 4, alpha=0.2, color='yellow')
# ์ฌ์ฉ์ ์ ์ ํจ์น ์ถ๊ฐ
rect = patches.Rectangle((7, 0.5), 2, 0.4, linewidth=1,
edgecolor='r', facecolor='lightblue', alpha=0.5)
ax.add_patch(rect)
ax.text(8, 0.7, '๊ด์ฌ ์์ญ', ha='center')
# ์ ๋ชฉ๊ณผ ๋ ์ด๋ธ
ax.set_title('์ฃผ์์ด ์๋ ๊ทธ๋ํ', fontsize=14)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
# ์ฌ์ฉ ์์
advanced = AdvancedPlotting()
# 3D ํ๋ฉด ํ๋กฏ
advanced.plot_3d_surface()
# ๋ค๋ฅธ ํจ์๋ก 3D ํ๋กฏ
advanced.plot_3d_surface(
func=lambda x, y: np.cos(x) * np.sin(y),
cmap='plasma',
view_angle=(40, 30)
)
# ์ ๋๋ฉ์ด์
advanced.create_animation(save_path='wave_animation.gif')
# ์ฃผ์์ด ์๋ ํ๋กฏ
advanced.custom_plot_with_annotations()
โ
ํน์ง:
- 3D ์๊ฐํ
- ๋ณต์กํ ๋ฐ์ดํฐ ํํ
- ์ธํฐ๋ํฐ๋ธ ๊ธฐ๋ฅ
- ์ ๋๋ฉ์ด์
- ์ฃผ์ ๋ฐ ๊ฐ์กฐ
- ์ฌ์ฉ์ ์ ์ ์์
โ
๋ชจ๋ฒ ์ฌ๋ก:
- ๊ทธ๋ํ ํฌ๊ธฐ ์กฐ์ : ๋ชฉ์ ์ ๋ง๋ ์ ์ ํ ํฌ๊ธฐ์ ๋น์จ์ ์ฌ์ฉํ์ฌ ๊ฐ๋ ์ฑ์ ๋์ธ๋ค.
- ๋ ์ด์์ ์ต์ ํ: ์ฌ๋ฌ ๊ทธ๋ํ๋ฅผ ํ์ํ ๋
tight_layout()
์ด๋constrained_layout=True
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒน์นจ์ ๋ฐฉ์งํ๋ค. - ์คํ์ผ ์ผ๊ด์ฑ ์ ์ง: ๋์ผํ ๋ณด๊ณ ์๋ ํ๋ก์ ํธ ๋ด์์ ์ผ๊ด๋ ์คํ์ผ๊ณผ ์ปฌ๋ฌ๋งต์ ์ฌ์ฉํ๋ค.
- ์ปฌ๋ฌ๋งต ์ ํ: ๋ฐ์ดํฐ ์ ํ์ ์ ํฉํ ์ปฌ๋ฌ๋งต์ ์ ํํ๊ณ , ์์ฝ์๋ฅผ ์ํด viridis ๊ณ์ด์ ๊ณ ๋ คํ๋ค.
- ๊ฐ๋ ์ฑ ๊ณ ๋ ค: ์ ์ ํ ๊ธ๊ผด ํฌ๊ธฐ, ๋ฒ๋ก ์์น, ์ถ ๋ ์ด๋ธ์ ์ฌ์ฉํ์ฌ ๊ฐ๋ ์ฑ์ ๋์ธ๋ค.
- ์ ์ฅ ํฌ๋งท ์ ํ: ๋ชฉ์ ์ ๋ง๋ ์ ์ ํ ํ์ผ ํ์(PNG, SVG, PDF)๊ณผ ํด์๋๋ฅผ ์ ํํ๋ค.
- ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ: ๋๊ท๋ชจ ๋ฐ์ดํฐ ์๊ฐํ ์
plt.close()
๋ฅผ ํธ์ถํ์ฌ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ค. - ์ธํฐ๋ํฐ๋ธ ๊ธฐ๋ฅ ํ์ฉ: ํ์์ ๋ฐ๋ผ ipywidgets์ด๋ plotly์ ๊ฐ์ ์ธํฐ๋ํฐ๋ธ ๋๊ตฌ๋ฅผ ๊ณ ๋ คํ๋ค.
- ๋ ์ด๋ธ๋ง ๋ช ํํ: ๋ชจ๋ ์ถ, ๋ฒ๋ก, ์ ๋ชฉ์ ๋ช ํํ๊ฒ ๋ ์ด๋ธ๋งํ์ฌ ํด์์ ์ฉ์ดํ๊ฒ ํ๋ค.
- ๊ทธ๋ฆฌ๋ ํ์ฉ: ๋ฐ์ดํฐ ํ๋ ์ ๋๊ธฐ ์ํด ์ ์ ํ ๊ทธ๋ฆฌ๋ ์ค์ ์ ์ฌ์ฉํ๋ค.
- ๊ฐ์ฒด ์งํฅ API ์ฌ์ฉ: ๋ณต์กํ ๊ทธ๋ํ๋ plt ํจ์๋ณด๋ค fig, ax ๊ฐ์ฒด๋ฅผ ํ์ฉํ์ฌ ๋ ์ธ๋ฐํ๊ฒ ์ ์ดํ๋ค.
- ํจ์ํ: ๋ฐ๋ณต์ ์ธ ์๊ฐํ ์์ ์ ํจ์๋ ํด๋์ค๋ก ๋ชจ๋ํํ์ฌ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋์ธ๋ค.