---
name: charts
description: Turn numbers into clean, report-ready charts — line (trends/prices), bar/column (comparisons), scatter (driver vs target), and a forecast plot with a confidence band. Saves PNG/SVG for embedding into a docx/pptx/pdf report, or an interactive HTML. Use after data-analysis / forecasting when the user wants a visual.
---

# Charts (report-ready visuals)

Make the chart that carries the point — for a document, export **PNG/SVG** (matplotlib); for an interactive web view, export **HTML** (plotly). Run through Bash on absolute paths.

## Preflight — Python + library (install on demand)
1. **Find Python.** `python3 --version`, else `python --version` (call it `PY`). If neither exists, guide the user once (in their language) to a one-time install — macOS `brew install python` · Windows `winget install -e --id Python.Python.3.12` (or python.org, add to PATH) · Linux `sudo apt install -y python3 python3-pip` — then wait; never fake a chart.
2. Install per output:
   ```bash
   PY -c "import matplotlib" 2>/dev/null || PY -m pip install --quiet --user matplotlib pandas   # PNG/SVG for reports
   PY -c "import plotly" 2>/dev/null     || PY -m pip install --quiet --user plotly              # interactive HTML
   ```

## Pick the chart by the message
- **Trend / price over time → line.** Time on x, value on y; multiple series = one line each.
- **Compare categories → bar / column.** Sort bars by value; horizontal bars for long labels.
- **Driver vs target → scatter** (optionally a fit line) — visualize a correlation from data-analysis.
- **Forecast → line + shaded interval** (history solid, forecast dashed, low/high as a filled band).
- Avoid pie charts for more than ~3 slices; avoid dual y-axes unless the two series truly share an x.

## Line / bar (matplotlib → PNG for a report)
```python
import matplotlib
matplotlib.use("Agg")                              # headless, no display needed
import matplotlib.pyplot as plt, pandas as pd

df = pd.read_csv("/abs/monthly.csv", parse_dates=["date"])
fig, ax = plt.subplots(figsize=(9, 5), dpi=150)
ax.plot(df["date"], df["price"], marker="o", label="Price")
ax.set_title("Price trend"); ax.set_xlabel("Month"); ax.set_ylabel("Price (¥)")
ax.grid(True, alpha=.3); ax.legend()
fig.autofmt_xdate(); fig.tight_layout()
fig.savefig("/abs/out/price_trend.png"); plt.close(fig)
```
CJK labels: if titles/labels are Chinese and show as boxes, set a CJK-capable font, e.g.
`matplotlib.rcParams["font.sans-serif"] = ["PingFang SC","Microsoft YaHei","Noto Sans CJK SC"]` and `rcParams["axes.unicode_minus"] = False`.

## Forecast plot (history + dashed forecast + confidence band)
```python
ax.plot(hist.index, hist.values, label="Actual")
ax.plot(fc.index, fc["mean"], "--", label="Forecast")
ax.fill_between(fc.index, fc["low"], fc["high"], alpha=.2, label="80% interval")
ax.legend()
```
Always show the interval band, not a bare forecast line — mirror what the forecasting skill reports.

## Interactive HTML (plotly)
```python
import plotly.express as px
fig = px.line(df, x="date", y="price", title="Price trend")
fig.write_html("/abs/out/price_trend.html", include_plotlyjs="cdn")
```
Use `include_plotlyjs="inline"` for a fully self-contained file (larger) that works offline.

## Embed into a report
Save the PNG, then place it with the document skill:
- **docx**: `doc.add_picture("/abs/out/price_trend.png", width=Inches(5.5))`
- **pptx**: `slide.shapes.add_picture("/abs/out/price_trend.png", Inches(1), Inches(1.5), width=Inches(8))`
- **pdf (weasyprint)**: reference the PNG in the HTML.

## Conventions
- Chart real, cited numbers only — a chart makes a claim look authoritative, so never plot invented data.
- Always title the chart, label both axes with units, and note the source/date in the report near it.
- Save to an absolute path and report it. Reply in the user's own language.
