chart-generator について
データ可視化向けのチャート生成スキルです。データと目的に合わせた図表の選択、スタイル調整、静的形式やインタラクティブな HTML への出力を案内します。
主な機能
- 01データに応じたチャート形式の選択
- 02統計図や関係図の作成
- 03テーマ、ラベル、凡例の調整
- 04PNG、SVG、PDF へのエクスポート
- 05インタラクティブな HTML チャートの生成
活用シーン
- 01カテゴリ別データの比較
- 02時系列の傾向の表示
- 03分布や変数間の関係の確認
- 04レポートやウェブページへの図表の埋め込み
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ curiouslearner/ devkit --skill chart-generatorインストール後、Claude Code で/chart-generatorを入力して読み込まれたか確認します。
詳細
チャート生成スキル
さまざまなチャートライブラリと形式を使用して、データからチャートや可視化を生成します。
手順
あなたはデータ可視化のエキスパートです。呼び出されたときは、次のようにします。
-
データを分析する:
- データの構造と型を理解する
- 適切なチャートタイプを特定する
- データのパターンと傾向を検出する
- 集計と統計を計算する
- 可視化の目的を決定する
-
チャートを生成する:
- 棒グラフ、折れ線グラフ、円グラフ、散布図を作成する
- ヒートマップとツリーマップを生成する
- ヒストグラムと箱ひげ図を作成する
- 時系列の可視化を構築する
- 多次元チャートを設計する
-
スタイルを設定してカスタマイズする:
- 配色とテーマを適用する
- ラベル、凡例、注釈を追加する
- 軸と目盛線をフォーマットする
- ツールチップとインタラクションをカスタマイズする
- アクセシビリティと可読性を確保する
-
エクスポートして埋め込む:
- PNG、SVG、PDF として保存する
- インタラクティブな HTML チャートを生成する
- Markdown レポートに埋め込む
- チャート API を作成する
- レスポンシブデザインをサポートする
使用例
@chart-generator data.csv --type bar
@chart-generator --line --time-series
@chart-generator --pie --group-by category
@chart-generator --scatter x:age y:income
@chart-generator --heatmap --correlation
@chart-generator --interactive --html
チャートタイプとユースケース
各チャートタイプを使うべき場面
| チャートタイプ | 最適な用途 | ユースケースの例 |
|---|---|---|
| 棒グラフ | カテゴリの比較 | 製品別の売上 |
| 折れ線グラフ | 時間経過に伴う傾向 | 月別の収益 |
| 円グラフ | 部分と全体の関係 | 市場シェア |
| 散布図 | 変数間の関係 | 身長と体重 |
| ヒストグラム | 値の分布 | 年齢分布 |
| 箱ひげ図 | 統計的分布 | 部門別の給与範囲 |
| ヒートマップ | 行列データ、相関 | 特徴量の相関 |
| 面グラフ | 累積的な傾向 | 積み上げ収益ストリーム |
| バブルチャート | 3 次元データ | 売上 vs 利益 vs 市場シェア |
| ツリーマップ | 階層データ | ディスク容量の使用量 |
Python - Matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
def create_bar_chart(data, x_col, y_col, title='Bar Chart', output='chart.png'):
"""
Create a bar chart
"""
plt.figure(figsize=(10, 6))
if isinstance(data, pd.DataFrame):
x = data[x_col]
y = data[y_col]
else:
x = data['labels']
y = data['values']
bars = plt.bar(x, y, color='steelblue', alpha=0.8)
# Add value labels on bars
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, fontsize=16, fontweight='bold')
plt.xlabel(x_col if isinstance(data, pd.DataFrame) else 'Category', fontsize=12)
plt.ylabel(y_col if isinstance(data, pd.DataFrame) else 'Value', fontsize=12)
plt.xticks(rotation=45, ha='right')
plt.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.savefig(output, dpi=300, bbox_inches='tight')
plt.close()
return output
def create_line_chart(data, x_col, y_col, title='Line Chart', output='chart.png'):
"""
Create a line chart
"""
plt.figure(figsize=(12, 6))
if isinstance(data, pd.DataFrame):
x = data[x_col]
y = data[y_col]
else:
x = data['x']
y = data['y']
plt.plot(x, y, marker='o', linewidth=2, markersize=6, color='steelblue')
# Add grid
plt.grid(True, alpha=0.3)
plt.title(title, fontsize=16, fontweight='bold')
plt.xlabel(x_col if isinstance(data, pd.DataFrame) else 'X', fontsize=12)
plt.ylabel(y_col if isinstance(data, pd.DataFrame) else 'Y', fontsize=12)
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.savefig(output, dpi=300, bbox_inches='tight')
plt.close()
return output
def create_pie_chart(data, labels_col, values_col, title='Pie Chart', output='chart.png'):
"""
Create a pie chart
"""
plt.figure(figsize=(10, 8))
if isinstance(data, pd.DataFrame):
labels = data[labels_col]
values = data[values_col]
else:
labels = data['labels']
values = data['values']
# Create color palette
colors = plt.cm.Set3(np.linspace(0, 1, len(labels)))
# Create pie chart
wedges, texts, autotexts = plt.pie(
values,
labels=labels,
autopct='%1.1f%%',
startangle=90,
colors=colors,
explode=[0.05] * len(labels) # Slightly separate slices
)
# Style percentage text
for autotext in autotexts:
autotext.set_color('white')
autotext.set_fontweight('bold')
autotext.set_fontsize(10)
plt.title(title, fontsize=16, fontweight='bold')
plt.axis('equal')
plt.tight_layout()
plt.savefig(output, dpi=300, bbox_inches='tight')
plt.close()
return output
def create_scatter_plot(data, x_col, y_col, color_col=None, size_col=None,
title='Scatter Plot', output='chart.png'):
"""
Create a scatter plot
"""
plt.figure(figsize=(10, 8))
if isinstance(data, pd.DataFrame):
x = data[x_col]
y = data[y_col]
c = data[color_col] if color_col else None
s = data[size_col] if size_col else 50
else:
x = data['x']
y = data['y']
c = None
s = 50
scatter = plt.scatter(x, y, c=c, s=s, alpha=0.6, cmap='viridis')
if color_col:
plt.colorbar(scatter, label=color_col)
# Add trend line
z = np.polyfit(x, y, 1)
p = np.poly1d(z)
plt.plot(x, p(x), "r--", alpha=0.8, label='Trend')
plt.title(title, fontsize=16, fontweight='bold')
plt.xlabel(x_col if isinstance(data, pd.DataFrame) else 'X', fontsize=12)
plt.ylabel(y_col if isinstance(data, pd.DataFrame) else 'Y', fontsize=12)
plt.grid(True, alpha=0.3)
plt.legend()
plt.tight_layout()
plt.savefig(output, dpi=300, bbox_inches='tight')
plt.close()
return output
def create_histogram(data, column, bins=30, title='Histogram', output='chart.png'):
"""
Create a histogram
"""
plt.figure(figsize=(10, 6))
if isinstance(data, pd.DataFrame):
values = data[column]
else:
values = data
n, bins, patches = plt.hist(values, bins=bins, color='steelblue',
alpha=0.7, edgecolor='black')
# Add mean line
mean_val = np.mean(values)
plt.axvline(mean_val, color='red', linestyle='dashed', linewidth=2,
label=f'Mean: {mean_val:.2f}')
# Add median line
median_val = np.median(values)
plt.axvline(median_val, color='green', linestyle='dashed', linewidth=2,
label=f'Median: {median_val:.2f}')
plt.title(title, fontsize=16, fontweight='bold')
plt.xlabel(column if isinstance(data, pd.DataFrame) else 'Value', fontsize=12)
plt.ylabel('Frequency', fontsize=12)
plt.legend()
plt.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.savefig(output, dpi=300, bbox_inches='tight')
plt.close()
return output
def create_box_plot(data, columns, title='Box Plot', output='chart.png'):
"""
Create a box plot
"""
plt.figure(figsize=(10, 6))
if isinstance(data, pd.DataFrame):
data_to_plot = [data[col].dropna() for col in columns]
labels = columns
else:
data_to_plot = data
labels = [f'Group {i+1}' for i in range(len(data))]
bp = plt.boxplot(data_to_plot, labels=labels, patch_artist=True)
# Color boxes
for patch in bp['boxes']:
patch.set_facecolor('lightblue')
patch.set_alpha(0.7)
plt.title(title, fontsize=16, fontweight='bold')
plt.ylabel('Value', fontsize=12)
plt.grid(axis='y', alpha=0.3)
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.savefig(output, dpi=300, bbox_inches='tight')
plt.close()
return output
def create_heatmap(data, title='Heatmap', output='chart.png'):
"""
Create a heatmap (correlation matrix)
"""
plt.figure(figsize=(10, 8))
if isinstance(data, pd.DataFrame):
# Calculate correlation matrix
corr_matrix = data.corr()
else:
corr_matrix = data
# Create heatmap
im = plt.imshow(corr_matrix, cmap='coolwarm', aspect='auto',
vmin=-1, vmax=1)
# Add colorbar
cbar = plt.colorbar(im)
cbar.set_label('Correlation', rotation=270, labelpad=20)
# Set ticks and labels
plt.xticks(range(len(corr_matrix.columns)), corr_matrix.columns,
rotation=45, ha='right')
plt.yticks(range(len(corr_matrix.columns)), corr_matrix.columns)
# Add correlation values
for i in range(len(corr_matrix)):
for j in range(len(corr_matrix.columns)):
text = plt.text(j, i, f'{corr_matrix.iloc[i, j]:.2f}',
ha='center', va='center', color='black', fontsize=9)
plt.title(title, fontsize=16, fontweight='bold', pad=20)
plt.tight_layout()
plt.savefig(output, dpi=300, bbox_inches='tight')
plt.close()
return output
Python - Seaborn
import seaborn as sns
def create_seaborn_chart(data, chart_type, x, y=None, hue=None,
title='Chart', output='chart.png'):
"""
Create charts using Seaborn
"""
plt.figure(figsize=(12, 6))
# Set style
sns.set_style("whitegrid")
sns.set_palette("husl")
if chart_type == 'bar':
sns.barplot(data=data, x=x, y=y, hue=hue)
elif chart_type == 'line':
sns.lineplot(data=data, x=x, y=y, hue=hue, marker='o')
elif chart_type == 'scatter':
sns.scatterplot(data=data, x=x, y=y, hue=hue, size=hue, alpha=0.6)
elif chart_type == 'box':
sns.boxplot(data=data, x=x, y=y, hue=hue)
elif chart_type == 'violin':
sns.violinplot(data=data, x=x, y=y, hue=hue)
elif chart_type == 'dist':
sns.histplot(data=data, x=x, hue=hue, kde=True)
elif chart_type == 'heatmap':
sns.heatmap(data.corr(), annot=True, fmt='.2f', cmap='coolwarm',
center=0, square=True, linewidths=1)
elif chart_type == 'pairplot':
# Special case - creates its own figure
g = sns.pairplot(data, hue=hue)
g.savefig(output, dpi=300, bbox_inches='tight')
return output
plt.title(title, fontsize=16, fontweight='bold')
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.savefig(output, dpi=300, bbox_inches='tight')
plt.close()
return output
# Advanced Seaborn visualizations
def create_facet_grid(data, x, y, col=None, row=None, hue=None,
title='Facet Grid', output='chart.png'):
"""
Create faceted charts
"""
g = sns.FacetGrid(data, col=col, row=row, hue=hue, height=4)
g.map(sns.scatterplot, x, y, alpha=0.6)
g.add_legend()
g.fig.suptitle(title, y=1.02, fontsize=16, fontweight='bold')
plt.savefig(output, dpi=300, bbox_inches='tight')
plt.close()
return output
JavaScript - Chart.js
const { ChartJSNodeCanvas } = require('chartjs-node-canvas');
async function createBarChart(data, options = {}) {
const width = options.width || 800;
const height = options.height || 600;
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });
const configuration = {
type: 'bar',
data: {
labels: data.labels,
datasets: [{
label: options.label || 'Dataset',
data: data.values,
backgroundColor: 'rgba(54, 162, 235, 0.6)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 2
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: options.title || 'Bar Chart',
font: { size: 18 }
},
legend: {
display: true,
position: 'top'
}
},
scales: {
y: {
beginAtZero: true
}
}
}
};
const imageBuffer = await chartJSNodeCanvas.renderToBuffer(configuration);
return imageBuffer;
}
async function createLineChart(data, options = {}) {
const width = options.width || 800;
const height = options.height || 600;
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });
const configuration = {
type: 'line',
data: {
labels: data.labels,
datasets: [{
label: options.label || 'Dataset',
data: data.values,
borderColor: 'rgba(75, 192, 192, 1)',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderWidth: 2,
tension: 0.4
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: options.title || 'Line Chart',
font: { size: 18 }
}
},
scales: {
y: {
beginAtZero: true
}
}
}
};
const imageBuffer = await chartJSNodeCanvas.renderToBuffer(configuration);
return imageBuffer;
}
async function createPieChart(data, options = {}) {
const width = options.width || 800;
const height = options.height || 600;
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });
const configuration = {
type: 'pie',
data: {
labels: data.labels,
datasets: [{
data: data.values,
backgroundColor: [
'rgba(255, 99, 132, 0.6)',
'rgba(54, 162, 235, 0.6)',
'rgba(255, 206, 86, 0.6)',
'rgba(75, 192, 192, 0.6)',
'rgba(153, 102, 255, 0.6)',
'rgba(255, 159, 64, 0.6)'
],
borderWidth: 2
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: options.title || 'Pie Chart',
font: { size: 18 }
},
legend: {
position: 'right'
}
}
}
};
const imageBuffer = await chartJSNodeCanvas.renderToBuffer(configuration);
return imageBuffer;
}
インタラクティブチャート - Plotly
import plotly.express as px
import plotly.graph_objects as go
def create_interactive_bar(data, x, y, title='Bar Chart', output='chart.html'):
"""
Create interactive bar chart with Plotly
"""
fig = px.bar(data, x=x, y=y, title=title,
color=y, color_continuous_scale='Viridis')
fig.update_layout(
font=dict(size=14),
showlegend=True,
hovermode='x unified'
)
fig.write_html(output)
return output
def create_interactive_line(data, x, y, title='Line Chart', output='chart.html'):
"""
Create interactive line chart
"""
fig = px.line(data, x=x, y=y, title=title, markers=True)
fig.update_traces(line=dict(width=3))
fig.update_layout(
hovermode='x unified',
font=dict(size=14)
)
fig.write_html(output)
return output
def create_interactive_scatter(data, x, y, color=None, size=None,
title='Scatter Plot', output='chart.html'):
"""
Create interactive scatter plot
"""
fig = px.scatter(data, x=x, y=y, color=color, size=size,
title=title, hover_data=data.columns)
fig.update_traces(marker=dict(line=dict(width=0.5, color='white')))
fig.write_html(output)
return output
def create_3d_scatter(data, x, y, z, color=None, title='3D Scatter',
output='chart.html'):
"""
Create 3D scatter plot
"""
fig = px.scatter_3d(data, x=x, y=y, z=z, color=color, title=title)
fig.update_layout(scene=dict(
xaxis_title=x,
yaxis_title=y,
zaxis_title=z
))
fig.write_html(output)
return output
def create_time_series(data, date_col, value_col, title='Time Series',
output='chart.html'):
"""
Create time series chart
"""
fig = go.Figure()
fig.add_trace(go.Scatter(
x=data[date_col],
y=data[value_col],
mode='lines+markers',
name=value_col,
line=dict(width=2),
marker=dict(size=6)
))
# Add range slider
fig.update_xaxes(
rangeslider_visible=True,
rangeselector=dict(
buttons=list([
dict(count=7, label="1w", step="day", stepmode="backward"),
dict(count=1, label="1m", step="month", stepmode="backward"),
dict(count=3, label="3m", step="month", stepmode="backward"),
dict(count=1, label="1y", step="year", stepmode="backward"),
dict(step="all")
])
)
)
fig.update_layout(
title=title,
xaxis_title=date_col,
yaxis_title=value_col,
font=dict(size=14)
)
fig.write_html(output)
return output
def create_dashboard(data, output='dashboard.html'):
"""
Create multi-chart dashboard
"""
from plotly.subplots import make_subplots
fig = make_subplots(
rows=2, cols=2,
subplot_titles=('Bar Chart', 'Line Chart', 'Pie Chart', 'Scatter Plot'),
specs=[[{'type': 'bar'}, {'type': 'scatter'}],
[{'type': 'pie'}, {'type': 'scatter'}]]
)
# Add charts
# Bar chart
fig.add_trace(
go.Bar(x=data['category'], y=data['value1'], name='Bar'),
row=1, col=1
)
# Line chart
fig.add_trace(
go.Scatter(x=data['date'], y=data['value2'], mode='lines', name='Line'),
row=1, col=2
)
# Pie chart
fig.add_trace(
go.Pie(labels=data['category'], values=data['value1'], name='Pie'),
row=2, col=1
)
# Scatter plot
fig.add_trace(
go.Scatter(x=data['value1'], y=data['value2'], mode='markers', name='Scatter'),
row=2, col=2
)
fig.update_layout(height=800, showlegend=True, title_text="Dashboard")
fig.write_html(output)
return output
チャートのスタイリングとテーマ
# Matplotlib themes
def apply_matplotlib_theme(theme='default'):
"""
Apply theme to matplotlib charts
"""
themes = {
'default': 'seaborn-v0_8-darkgrid',
'minimal': 'seaborn-v0_8-whitegrid',
'dark': 'dark_background',
'classic': 'classic',
'ggplot': 'ggplot'
}
plt.style.use(themes.get(theme, 'default'))
# Custom color palettes
COLOR_PALETTES = {
'corporate': ['#003f5c', '#58508d', '#bc5090', '#ff6361', '#ffa600'],
'pastel': ['#a8e6cf', '#dcedc1', '#ffd3b6', '#ffaaa5', '#ff8b94'],
'vibrant': ['#e74c3c', '#3498db', '#2ecc71', '#f39c12', '#9b59b6'],
'monochrome': ['#2c3e50', '#34495e', '#7f8c8d', '#95a5a6', '#bdc3c7']
}
def apply_color_palette(palette_name='corporate'):
"""Apply custom color palette"""
colors = COLOR_PALETTES.get(palette_name, COLOR_PALETTES['corporate'])
plt.rcParams['axes.prop_cycle'] = plt.cycler(color=colors)
エクスポート形式
def export_chart_multiple_formats(fig, base_name='chart'):
"""
Export chart in multiple formats
"""
formats = {
'png': {'dpi': 300, 'transparent': False},
'svg': {'format': 'svg'},
'pdf': {'format': 'pdf'},
'jpg': {'dpi': 300, 'format': 'jpg'}
}
files = []
for fmt, kwargs in formats.items():
output_file = f"{base_name}.{fmt}"
fig.savefig(output_file, bbox_inches='tight', **kwargs)
files.append(output_file)
return files
チャート生成パイプライン
def generate_charts_from_data(data, chart_configs, output_dir='charts'):
"""
Generate multiple charts from data based on configurations
chart_configs = [
{
'type': 'bar',
'x': 'category',
'y': 'value',
'title': 'Sales by Category',
'output': 'sales_bar.png'
},
...
]
"""
import os
os.makedirs(output_dir, exist_ok=True)
generated_charts = []
for config in chart_configs:
chart_type = config['type']
output = os.path.join(output_dir, config['output'])
if chart_type == 'bar':
create_bar_chart(data, config['x'], config['y'],
config.get('title', 'Chart'), output)
elif chart_type == 'line':
create_line_chart(data, config['x'], config['y'],
config.get('title', 'Chart'), output)
elif chart_type == 'pie':
create_pie_chart(data, config['x'], config['y'],
config.get('title', 'Chart'), output)
elif chart_type == 'scatter':
create_scatter_plot(data, config['x'], config['y'],
config.get('color'), config.get('size'),
config.get('title', 'Chart'), output)
elif chart_type == 'heatmap':
create_heatmap(data, config.get('title', 'Chart'), output)
generated_charts.append({
'type': chart_type,
'title': config.get('title'),
'file': output
})
return generated_charts
ベストプラクティス
- データに適切なチャートタイプを選択する
- 明確で説明的なタイトルとラベルを使用する
- チャート全体で一貫した配色を適用する
- 可読性を確保する(フォントサイズ、コントラスト)
- コンテキストを追加する(注釈、参照線)
- 高解像度でエクスポートする(最低 300 DPI)
- アクセシビリティを考慮する(色覚多様性に配慮したパレット)
- さまざまな画面サイズでテストする(レスポンシブデザイン)
- ウェブ利用のためにファイルサイズを最適化する
- 再現性のためにチャート生成コードを文書化する
一般的なチャートパターン
比較チャート
- カテゴリ比較には棒グラフ
- 複数系列の比較にはグループ化棒グラフ
- 部分と全体の比較には積み上げ棒グラフ
傾向チャート
- 時系列には折れ線グラフ
- 累積的な傾向には面グラフ
- インラインの傾向にはスパークライン
分布チャート
- 度数分布にはヒストグラム
- 統計的分布には箱ひげ図
- 分布の形状にはバイオリンプロット
関係チャート
- 相関には散布図
- 3 次元の関係にはバブルチャート
- 行列の関係にはヒートマップ
構成チャート
- 単純な部分と全体には円グラフ
- 時間経過に伴う傾向には積み上げ面グラフ
- 階層的な構成にはツリーマップ
注意事項
- 常に軸にラベルを付け、単位を示してください
- 適切なスケール(線形、対数)を使用してください
- データインク比を考慮してください(チャートジャンクを最小限にする)
- さまざまなデータ範囲でチャートをテストしてください
- 複数の系列を使用する場合は凡例を提供してください
- 主要な洞察を強調するために注釈を使用してください
- 出版物向けにはベクター形式でチャートをエクスポートしてください
- 関連するチャート全体で配色を一貫させてください
- 色の意味における文化的な違いを考慮してください
- 可視化の前にデータを検証してください
コメント
Markdown 対応