smart-charts について
smart-chartsは、Agent向けのデータ可視化スキルで、CSV、Excel、JSONからインタラクティブなECharts HTMLを生成します。32種類のチャート、テーマ、複数ファイル処理に対応し、データ変換コードはサンドボックスで実行します。
主な機能
- 01CSV、Excel、JSONをインタラクティブなECharts HTMLに変換
- 0232種類のチャートに対応
- 033種類のテーマプリセット
- 04複数ファイルの結合
- 05サンドボックスでデータ変換を実行
- 06データを分析してからチャートを選択
活用シーン
- 01表形式データからチャートを生成
- 02分析意図が未指定のデータから可視化を選択
- 03集計やピボット後のデータを可視化
- 04チャートのデータ範囲と統計概要を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hherosoul/ dsh-smart-charts --skill smart-chartsインストール後、Claude Code で/smart-chartsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
requirements.txtassets/echarts-liquidfill.min.jsecharts-wordcloud.min.jsreferences/REFERENCE.mdscripts/__init__.py_bootstrap.pychart_generator.pycli.pydata_parser.pydata_transformer.pyexceptions.pyplot_stats.pyprofile.pyregression_check.pyrenderers.pystats_kernels.pytemplate.pytexts.pythemes.py詳細
スマートチャート
データファイル(CSV/Excel/JSON)をインタラクティブな ECharts HTML に変換します。32 種類のチャートタイプ、3 種類のテーマプリセット(default/classic/dark)、複数ファイルの統合、LLM によるデータ変換コード(サンドボックス実行)に対応しています。 CLI の全パラメーター、フラグのセマンティクス、複数チャート/複数ファイルの詳細、機能の制限、エラーコード一覧、成果物の読み解きに関する完全な仕様、FAQ については REFERENCE.md をご覧ください。
起動トリガー
TRIGGER
- ユーザーが表形式のデータファイルを提供または指定し、作図、可視化、チャートの生成を求めている
- ユーザーが「作図」「チャートを作成」「チャートを生成」「データ可視化」「chart」「visualization」に言及している
DO-NOT-TRIGGER(いずれかに該当する場合は、別のスキルを案内してください。このスキルで無理に対応しないでください)
- 結論を含むストーリー仕立てのレポート/週報/振り返り/報告書が必要 → レポート系のスキルを使用してください(本スキルは作図+追跡可能な事実+洞察の候補となるシグナルを提供しますが、ストーリー仕立ての文書は作成しません)
- データファイルがない(文章だけの説明、口頭でのアイデア)
- バックエンドのダッシュボード、画像/音声/動画など、表形式以外のコンテンツが必要
- 地図の描画:組み込みの中国の省級行政区画(
china、香港・マカオ・台湾を含む)と世界の国レベル(world、英語の国名と完全一致)に対応しています。市級/区・県級など、さらに細かい地域にはユーザー自身で用意した GeoJSON ファイル(--geo-path)が必要です。本スキルではダウンロードしません
ワークフロー(まずプロファイリングし、その後に選定)
chart_type は CLI の必須パラメーターですが、選定の根拠(母数、分布、粒度、エンティティと明細の区別)は、選定後に plot_stats で初めて得られます。先に決定してから根拠を集めると、選定が当てずっぽうになってしまいます。そのため、ユーザーが意図を明確に示しているかどうかで、次の 2 つのルートに分けます。
A. ユーザーの意図が明確(「地域ごとの売上を比較したい」「月次の傾向を見たい」「構成比を見たい」) → 選定表に従ってチャートタイプ+軸+集計方法を選び、作図します。ワークフローを進めるためだけに profile を実行しないでください。データが意図を満たせない場合(傾向を見たいのに時間列がない、構成比を見たいのに明細行しかないなど)は、事実をそのまま説明し、実現可能な代替案(例:「傾向」をカテゴリ別の比較に変更する)を提示してください。無理に作図しないでください。
B. ユーザーがデータだけを提供し、見たい内容を示していない(最も多いケース)→ 次の 2 つのコマンドを実行します。
python {skill_base}/scripts/cli.py <file> --profile(1 つのコマンド。読み取りのみで、描画もファイルへの書き込みもしません)。各列の dtype/基数/欠損率/サンプル/統計、エンティティの粒度(grain)、洞察候補のシグナル(signals)、データではない可能性のある行(row_quality)を取得します。- どの図を 1〜3 点出すかは、あなたが判断します。
columnsの dtype/サンプル/基数を確認して、どの列が ID、ディメンション、メジャーかを判断し、signalsを組み合わせて価値のある発見を選びます。それをもとにチャートタイプ+軸+集計方法を決め、直接作図します(集計/ピボットには--transform-code、結論には--title、解説には--annotationを使用)。成果物を渡す際には、「なぜこの図を選んだのか」を説明してください。
signalsの中で、優先して図にする価値が最も高いのはdivergent_category(逆方向に変化するカテゴリ)とtrendです。全体の平均に隠れやすく、「ユーザー自身は気づいていなかったが、見ればすぐわかる」発見につながりやすいためです。
MUST NOT 選定の責任をユーザーに押し戻さないでください(「傾向、比較、構成比のどれを見たいですか?」など)。どの列が ID、どの列がディメンションで、どの図を出すべきかは、エージェントがプロファイリングの客観的な事実から判断することであり、ユーザーにメニューから選ばせるものではありません。
仕様(8 項目、MUST)
- 列名は解析後に正規化されます。小文字に変換され、特殊文字は
_に置き換えられます(例:总学时→总_学时)。中国語の文字は保持されます。--x-axis/--y-axis/transform では、正規化後の列名を指定する必要があります。 - transform サンドボックスで使用できる変数は
df/pd/npのみです(np.select/np.whereは使用可能)。複数の文に対応しています(;または改行で区切ります)。resultという名前の DataFrame を生成する必要があります。import/open/try/クラス定義は禁止されています(ブラックリスト+AST ホワイトリストで強制検証され、違反するとsuggestionを含むエラーが返されます)。 - pie/bar/treemap/funnel などは、「カテゴリ列 1 つ+数値列 1 つ」としてデータを読み込みます。ドキュメント内の
name/valueは役割を指しており、列名をその名前にする必要はありません(元の列名を保持すると読みやすくなり、rename を追加で書く必要もありません)。カテゴリ別の頻度を示す図では、まず transform でこの 2 列に集計し、次に--x-axis <分類列> --y-axis <数値列>で指定します。 - 成功時の stdout には、
success/html_path/chart_type/title/source_rows/plotted_rows/unique_entities/data_rows/data_preview(描画データの先頭 10 行。集計方法の照合に使用)/annotation_source/plot_stats(描画データの完全な統計サマリー。解説に使用。32 種類すべてに対応)が含まれます。assumptions(CLI による自動選択)とadvisories(集計方法に関する注意)は、空でない場合にのみ表示されます。このフィールドがない場合は、「今回は自動選択/注意事項なし」を意味し、欠落ではありません。 - 集計方法の照合には stdout の
data_preview+data_rowsを直接確認し、HTML を開いてデータを検索しないでください。data_previewは描画フレーム内の x/y 列の先頭 10 行です(描画と同じデータソース、同じフレームですが、描画に使用していない補助列は含みません)。data_rowsは実際の描画行数です。transform で生成した補助列を確認する必要がある場合は、transform 内のprint(df.columns)/print(df.head())(stderr に出力され、stdout は汚染されません)を使用するか、別途--dry-runを実行してください。 - 集計方法の照合には
source_rows/plotted_rows/unique_entitiesを確認してください。source_rows=transform 前の元の行数、plotted_rows=実際の描画行数、unique_entities=重複を除いたエンティティ数(--label-colがあればその列を使用し、なければ x 列を使用)です。注意:plotted_rows == source_rowsは「集計なし」を示すだけです。散布図/箱ひげ図など、行を単位とする図は、そもそも集計すべきではありません。判定には図の意味を考慮し、汎用的なエラー判定として扱わないでください。実際の機械的な判定基準はadvisoriesの「集計漏れの疑い」です。x 軸の値の種類数が行数より少なく、そのチャートタイプが「1 つの x に対して y が 1 つ」を要求する場合、plot_statsの最大値/最小値/平均値はディメンション全体ではなく、行単位の値です。 - 意図が不明確な場合は、MUST 先に
--profileを実行してください(python {skill_base}/scripts/cli.py <file> --profile。チャートタイプの指定は不要です)。各列の dtype/基数/欠損率/サンプル/統計、grain、signals、row_qualityが返されます。これらは客観的な事実であり、選定の根拠です。どの列が ID、どの列がディメンションで、どの図を出すべきかは、これらの事実からあなた自身が判断してください。profile が代わりに判断することはありません(role の分類やチャートタイプの提案は行いません)。 - 成果物を渡す前に、MUST
assumptions+advisoriesを確認してください。assumptionsは CLI が代わりに行った自動選択(x/y の自動設定など)、advisoriesは「生成には成功しましたが、別の集計方法を希望する可能性があります」という注意(集計漏れの疑い、円グラフのカテゴリが多すぎる、数値列の一部が降格されているなど)です。どちらも成果物を渡す際に反映してください。ユーザーが想定に同意しない場合は、一言伝えるだけで再生成できます。
黄金の例(テンプレート。列名を置き換えてコピー)
1 カテゴリーの頻度 → pie/bar(最も頻度の高いシナリオ):
python {skill_base}/scripts/cli.py data.xlsx bar --title "标题" --output-dir ./out \
--x-axis name --y-axis value \
--transform-code "result = df['类别列'].fillna('未标注').value_counts().rename_axis('name').reset_index(name='value')"
(gauge/liquid で「達成率」を表示したい場合は、必ず --target <目標値> を追加してください。指定しないと plot_stats.achievement は null になります。環境を自己診断するには、python {skill_base}/scripts/cli.py --doctor を実行します。)
2 複数グラフを一括生成 + エスケープの落とし穴を回避(グラフが 2 枚以上の場合は MUST 一括生成。transform に中国語や引用符が含まれる場合、シェルで --charts を直接渡さず、JSON ファイルに書き込んで --charts-file を使用してください):
python {skill_base}/scripts/cli.py data.xlsx --sheet "Sheet1" \
--charts-file charts.json --output-dir ./out
charts.json の各項目:type(必須)+ title/x_axis/y_axis(文字列または配列)/transform_code(単一グラフ単位)/label_col/color_by/annotation。設定は エージェント自身が作成します。--profile の客観的な情報(dtype/カーディナリティ/サンプル/signals)に基づいて、作成するグラフと軸の設定を決定してください。
3 グループ化集計 → bar:
python {skill_base}/scripts/cli.py data.xlsx bar --title "标题" --output-dir ./out \
--x-axis 分组列 --y-axis 数值列 \
--transform-code "result = df.groupby('分组列')['数值列'].sum().reset_index()"
(reset_index() の後も列名は「グループ列/数値列」のままなので、軸からそのまま参照できます。rename_axis('name')+reset_index(name='value') に変更しても構いませんが、その場合は軸も name/value に変更してください。両者は一致させる必要があります。)
集計時の落とし穴:集計前に「データ行単位か、重複を除いたエンティティ単位か」を確認してください。エンティティの属性(各科目の授業時間の構成など)を集計する場合は、先に drop_duplicates を実行します。生成後は data_preview と照合して確認してください(各行の value の合計がエンティティ数ではなく元の行数と等しい場合は、重複除去を忘れています)。
厳守事項(MUST)
- MUST CLI ワークフローを使用すること(
data_parser.py→cli.py)。代わりに独自のスクリプトを書いてはいけません。 - 不正なヘッダーは MUST CLI フラグを使用すること(
--skiprows N/--header-row N/--drop-rows 0,1/--sheet。意味は REFERENCE.md を参照)。N は実際のデータに基づいて決定してください(まずフラグなしで実行し、元のレイアウトを確認します)。固定値を憶測で設定してはいけません。注:--skiprows Nと--header-row Nは同じ動作です(どちらも「N 行目をヘッダーとして使用し、その上の行を破棄」)。どちらか一方を選べばよく、N を別々の決定事項だと考えないでください。--header-rowの使用を推奨します。- 複数行ヘッダー + スコア行/サブヘッダー行(
--header-row Nでは「どの行を列名にするか」しか選べず、メインヘッダーを保持しながらサブヘッダーを結合することはできません)は3 段階で処理します。①--profileを実行し、row_quality.suspicious_non_data_rows(またはadvisories)を確認して、残っている非データ行の位置を特定します。②--drop-rows 0,1(位置は profile の結果に基づいて決定し、憶測で設定しないでください)または--transform-code "result = df.drop(index=[0,1])"を使って行を削除します。③--profileを再実行して問題が解消されたことを確認します(rowsが減少し、row_qualityの該当件数がゼロになってからグラフを作成してください)。
- 複数行ヘッダー + スコア行/サブヘッダー行(
- 列名の変更/データの再構成/集計には MUST
--transform-codeを使用すること。解析レイヤーで対応するのは「どの行がヘッダーか」だけです。それ以外のデータ整形は transform で行います。 - 軸名/系列名の表示を変更するには MUST
--x-name/--y-name/--series-name(s)を使用し、列名の変更で代用しないこと。列名を変更すると軸名と系列名の両方が変わります(どちらも列名に紐付いています)。また、デフォルトのテキストが固定されているグラフ(heatmap の「ヒートマップ」/gauge の「ゲージ」/sankey の「サンキー図」など)は、列名を変更しても系列名を変更できません。表示名が唯一の適切な指定方法です。--x-nameは x 軸、--y-nameは y 軸、--series-name(単一)または--series-names(複数。表示される系列の順)で系列名を変更してください。 - 未対応のシナリオは MUST 報告すること:CLI が実際に対応していないもの(ネストした JSON が 1 階層を超える場合など)は、まずユーザーに説明して提案を提示してください。黙って回避してはいけません。
- 生成コードに絶対パスをハードコードしてはいけません。実行時にパスを解決してください。
--langを自発的に渡さないでください。CLI はデータの言語に自動で従います。ユーザーが特定の言語を明確に指定した場合に限り渡してください。- 解釈を添えて納品すること MUST:グラフを納品するときは、LLM が作成した文章による解釈を必ず添え、
--annotationで HTML に挿入してください(以下の「解釈の納品規則」を参照)。グラフだけを納品してはいけません。成功時の出力にあるannotation_sourceは、解釈の出所を示します。'user'は渡した内容、'default'はコードがテンプレートを埋めた内容(この場合、出力に advisory も付きます)です。納品前に'user'であることを確認してください。 --output-dirを明示的に渡すこと MUST。ユーザーが確認できるディレクトリ(./out、デスクトップ、または現在の作業ディレクトリ内の明示的なサブディレクトリなど)を指定してください。デフォルト値の./smart_charts_outputは現在の作業ディレクトリに保存されるため、ユーザーが成果物を見つけにくくなります。{skill_base}= スキルのルートディレクトリ(SKILL.mdを含む)です。現在のホストがこのプレースホルダーを置換しない場合は、まず一度だけ場所を特定してから絶対パスに変更して使用してください:SKILL_DIR=$(dirname "$(find "$HOME" -maxdepth 6 -type f -path "*smart-charts/scripts/cli.py" | head -1)")/..。以降は$SKILL_DIR/scripts/cli.pyを使用します。記憶を頼りにパスを組み立ててはいけません。
デフォルトの方針(ユーザーに確認しない)
グラフの生成は、低コストで取り消し可能な操作です(再生成に 1~10 秒、外部への副作用はありません)。グラフの種類、複数ファイルの結合方法、値の集計基準は、エージェントが内部で決定し、ユーザーの作業を中断しません。判断の根拠は、ユーザーが明示した意図(分岐 A)または --profile が示す客観的な情報(dtype/カーディナリティ/サンプル/signals。分岐 B)です。
事前確認ではなく事後レビュー:納品時の説明に、今回採用した主な前提を明記してください(例:「month は時系列列のため、line を選択しました」「列名が完全に一致する複数ファイルを縦方向に結合し、source_file 列を追加しました」「売上高は金額を基準にしました」)。いずれかの前提にユーザーが同意しない場合は、基準/種類/結合方法の変更を一言で依頼するだけで、再生成できます。
ユーザーの介入が必須となる唯一の条件:Exit Criteria の「それでも失敗」分岐を参照してください。
終了条件(機械的に判定可能)
- ✅ 成功: stdout が
{"chart": {"success": true, ...}}(複数グラフモードでは{"charts": [...], "summary": ...})であり、html_pathが指すファイルが存在し、空でないこと → 同じ stdout のdata_preview/data_rows/plotted_rows/unique_entitiesを使って集計基準(行単位か、重複を除いたエンティティ単位か)を照合し、問題がないことを確認したうえで、文章による解釈を添えて納品します。 - ℹ️
--dry-runは納品とはみなしません。html_pathは null となり、ファイルも保存されず、列名の試行や集計スクリプトのテストにのみ使用します。解釈の作成に先立って実行する必要はありません。正式な出力にはplot_statsが含まれます。 - ❌ 失敗:
success: falseまたは終了コード 1 →error.details.suggestionを確認して修正後に再試行します。同じ段階での再試行は最大 2 回です。 - 🛑 それでも失敗(ユーザーの介入が必須となる唯一の条件):
code_name、suggestion、これまでに試した修正内容を正確にユーザーへ報告し、提案を提示して判断を待ってください。独自スクリプトに黙って切り替えて代替してはいけません(制約 1/4 に違反します)。
グラフの種類の選択表
種類を選ぶ前に Required Format を確認してください。一致しない場合は transform コードで適合させます。
単位に関する注意:heatmap/boxplot/radar などの複数列グラフで、各列の単位に大きな差がある場合(満点 10 と満点 100 が混在するなど)は、先に transform コードで正規化してください。そうしないと、単位の大きい列が単位の小さい列を圧倒します。 | ID | 最適な用途 | トリガーキーワード | y_axis | 必須のDataFrame形式 | |----|----------|------------------|:------:|---------------------------| |
line| 時系列の傾向 | 傾向, 変化, 時間の経過 | 1N | 1つのカテゴリ/時刻 + 1N個の数値 | |bar| カテゴリの比較 | 比較, 順位, 差異 | 1N | 1つのカテゴリ + 1N個の数値 | |area| 累積的な変化 | 累積, 変化 | 1N | 1つのカテゴリ/時刻 + 1N個の数値 | |pie| 構成比 | 割合, 構成, 比率 | 1 | 1つの名前 + 1つの値 | |scatter| 相関 | 相関, 関係, 散布図 | 1 | 2つの数値、または1つのカテゴリ + 1つの数値 | |radar| 多次元の比較 | 多次元, 総合, レーダー | N | 1つの指標 + N個の数値 | |heatmap| 密度/クロス集計 | 密度, クロス, 行列, ヒートマップ | 1N | 1つのカテゴリ + 1N個の数値(各列が行列の「列」です。クロス集計表は先に pivot_table で列に展開してください) | |treemap| 階層的な構成比 | 階層, 比率, 入れ子 | 1 | 1つの名前 + 1つの値 | |graph| エンティティ間の関係 | 関係, ネットワーク, トポロジー | special | source + target (+ value) | |boxplot| 分布/外れ値 | 分布, 外れ値, 四分位数 | N | N個の数値 | |waterfall| 増分の変化 | 増分, 変化, ウォーターフォール | 1 | 1つのカテゴリ + 1つの数値(増分) | |gauge| KPIの進捗 | 進捗, kpi, 達成 | 1 | 1つの数値(平均値を使用) | |sankey| フローの遷移 | フロー, 遷移, サンキー | special | source + target + value | |funnel| コンバージョン率 | コンバージョン, ファネル, 離脱 | 1 | 1つの名前 + 1つの値 | |sunburst| 単一レベルの構成比 | 比率, サンバースト | 1 | 1つの名前 + 1つの値 | |wordcloud| 頻度/キーワード | 単語頻度, キーワード, テキスト, ワードクラウド | 1 | 1つの名前 + 1つの値 | |histogram| 分布の形状 | 分布, ヒストグラム | 1 | 1つの数値列(--x-axisまたは--y-axisのどちらでも可。数値型の--x-axisを優先) | |stacked_bar| カテゴリごとの構成 | 構成, 積み上げ | 1N | 1つのカテゴリ + 1N個の数値 | |bubble| 3変数の相関 | バブル, 3変数 | 2 | 2つの数値 + 1つのサイズ | |pareto| 80/20分析 | パレート, 80/20 | 1 | 1つのカテゴリ + 1つの数値 | |combo| 二軸の比較 | 二軸, 複合 | 1N | 1つのカテゴリ + 1つの棒 + 1N本の線 | |venn| 集合の重なり(23集合) | 重なり, 共通部分, ベン図 | 1 | 1つの名前 + 1つの値。共通部分の行にはN | 1つのカテゴリ + 1A∩Bと名前を付けてください(区切り文字:∩ & + × と) | |mindmap| 階層的なアイデア | マインドマップ, アウトライン | 1 | 1つの親 + 1つの子(カテゴリ列) | |orgchart| 組織構造 | 組織図, 階層, 報告関係 | 1 | 1つの親 + 1つの子(カテゴリ列) | |liquid| 割合/進捗 | 液体, 進捗, パーセント, 完了率 | 1 | 1つの数値(平均値を使用) | |spreadsheet| 生データ表/ピボット表示 | 表, 詳細, スプレッドシート, 一覧 | N | 任意の列(x/y で表示列を任意に絞り込み可能。集計には transform を使用) | |map| 地理的なコロプレスマップ | 地図, 地域, 省, 地理 | 1 | 1つの地域名 + 1つの数値(デフォルトは中国の省レベル。--geo/--geo-pathで任意の地域に変更) | |lines| 地図上のルート/移動 | ルート, 移動, フローマップ | special | source + target (+ value)(デフォルトは省レベルの名称。--geo/--geo-pathで任意の地域に変更) | |effect_scatter| アニメーション散布図のハイライト | リップル, ハイライト, 散布図アニメーション | 1 | 2つの数値、または1つのカテゴリ + 1つの数値 | |calendar| 日次ヒートマップ(GitHub形式) | カレンダーヒートマップ, 日次アクティビティ | 1 | 1つの日付 + 1つの数値 | |pictorial_bar| シンボル/アイコン付き棒グラフ | ピクトリアル, アイコン付き棒, シンボル付き棒 | 1N個の数値 | |N | 1つの日付 + 1~N個の数値 |theme_river| 時間経過に伴うテーマの変化 | テーマリバー, イベントの変化 | 1
gauge/liquidで「達成率」を出すには--target <目標値>を渡す必要があります:achievement= mean ÷ target。指定しない場合、このフィールドはnullになります(自動推定された目盛り範囲は業務上の目標ではないため、比率に業務上の意味はありません)。また、出力には advisory が付加されます。 y_axis cardinality key:1= 最初の列のみ使用、1~N= 各列が系列になる、N= 複数列が必要、2= 数値列がちょうど2列必要、special= 関係図(graph/sankey/lines)は--x-axis(source)+--y-axis(target、value は任意)で明示的に指定し、列名の語彙リストによる自動検出は行いません。scatter/bubble/boxplot の識別列は--label-colで明示的に指定します。指定しない場合は識別情報を表示しません(tooltip には座標値のみ表示)。
Transform Code Contract
契約(サンドボックスによって強制されます。違反すると suggestion 付きのエラーが返るため、提示に従って修正してください):
- 使用できる変数は
df,pd,npのみです。resultという名前のpd.DataFrameを必ず生成してください。 dfを直接変更しないでください(df.copy()またはチェーン操作を使用してください)。- 元データがすでに目的の形式に一致している場合は、
--transform-codeを渡さないでください。
よく使う変換パターン:
- Long→複数系列:
result = df.pivot_table(index='<time>', columns='<category>', values='<value>', aggfunc='sum').reset_index() - Long→円グラフ(フィルター):
result = df[df['metric']=='revenue'][['category','value']].rename(columns={'category':'name'}) - Wide→Long:
result = df.melt(id_vars=['date'], var_name='name', value_name='value') - 集計→棒グラフ:
result = df.groupby('<category>')['<value>'].sum().reset_index() - 列名の変更:
result = df.rename(columns={'来源':'source','去向':'target','金额':'value'}) - 差分を計算→ウォーターフォール:
tmp = df.copy(); tmp['delta'] = tmp['profit'].diff().fillna(tmp['profit'].iloc[0]); result = tmp[['month','delta']] - 分かりにくい、または情報のない列名を変更(
--header-rowの後にscore_a,unnamed_3などの列名が残る場合):result = df.rename(columns={'unnamed_0':'student_id','unnamed_1':'name','score_a':'homework_score','score_b':'exam_score'}) - 結合セルの値を前方補完(グループの先頭行にのみ値が入力されている場合):
result = df.ffill() - データ以外の行を削除(位置は
--profileのrow_quality.suspicious_non_data_rowsで確認してください。推測で決めないでください。出力前に--drop-rowsで保存するのと同等ですが、transform 内で行うほうが分かりやすくなります):result = df.drop(index=[0,1]) - サブヘッダーを1つの列名に統合(
--header-row Nで1行をフラット化すると文脈が失われる場合):result = df.rename(columns={c: f'{c}_score' for c in df.columns if c not in ['student_id','name']})
クリーニング結果を確認する通常の方法:transform 内の
print(df.head())/print(df.columns)は stderr にリダイレクトされ、stdout の JSON 契約を汚染しません。そのため、transform 内で
納品時の解説規範(Delivery Annotation)
各グラフを納品する際は、LLM が書いた解説文(テンプレート文ではありません)を必ず添え、--annotation で HTML に挿入してください(グラフ下部の「グラフの説明」セクション)。
解説で答えるべきなのは「このデータで最も注目すべき発見は何か」であり、グラフに何が描かれているかの言い換えではありません。 スキルが事実を計算し、どの発見を伝える価値があるかを判断して明確に伝えるのは、エージェントの役割です。そのため、解説は「結論 → 根拠 → 前提・限界」の構成にし、「グラフの種類 → 最大値」の説明にはしません。
引用できる事実のソース(3つ):
profile.signals—— グラフ作成前の洞察候補(傾向の方向と増減率、上位の集中度、逆行するカテゴリ、外れ値、強い相関を示すペア)plot_stats/data_preview—— そのグラフで実際に描画されたデータの統計(最終的な基準はこちらです)assumptions/advisories—— CLI による自動選択と集計基準に関する注意事項
標準的な手順:
- 意図が明確でない場合は、まず
--profileを実行し、signalsから説明する発見を選び、それに基づいてグラフの種類と集計基準を決めます(「ワークフロー」の B 分岐を参照)。 --annotation "解説文"を付けて正式に生成します。正式な出力にはplot_statsとdata_previewがすでに含まれているため、数値を取得するために事前に--dry-runを実行する必要はありません。- その実行の
plot_statsを読み、解説に使う数値を確認します。解説を書き終えてから見直してください。集計基準やグラフを変更する必要があると分かった場合に限り、2回目の生成を行います。再生成は低コストで元に戻せる操作です(1~10秒)。
--dry-runは「先に数値を確認したいが、明確にファイルへ出力しない」場合にのみ使ってください(列名の試行錯誤や集計スクリプトのテストなど)。解説を書く前に必ず行う手順として扱うと、呼び出し回数が倍増するだけで何のメリットもありません。
解説の最小構成(2~4文、結論を先に):
- 発見:結論を一文で示します。「華南では4月から売上高が半減した一方、他の3地域は同時期も成長を続けた」と書き、「この図は各地域の月次売上高を示しています」とは書きません。
- 根拠:具体的な数値を1~2個、対応するラベルと出典(
plot_statsまたはprofile.signals)とともに示します。 - 前提・限界:集計方法、対象範囲、サンプル数などの集計基準を一文で説明し、
assumptions/advisoriesの仮定にも触れます。ユーザーがいずれかの仮定に同意しない場合は、一文の指示で再生成できます。
タイトルには結論、副題には集計基準を記載:--title には結論を示す短いフレーズ(主語・述語・目的語+数値、例:「売上高が前年比23%増加」)を使います。数値は plot_stats から直接取得し、「月別売上高」のような名詞句は使いません。期間、フィルター条件、データソースなどの文脈は --subtitle に記載し、タイトルには入れません。
厳守事項:
- 解説に含める各数値は、必ず
plot_stats/data_preview/profile.signalsのいずれかで確認できるものにしてください。記憶や印象で作り上げてはいけません。x_cardinalityは重複を除いた件数です。x 列の意味に合わせて表現してください(x が「氏名」なら「59名の学生」とし、「59カテゴリ」とはしません)。 - 根拠で裏付けられる事実のみを述べてください。「なぜか/どうすべきか」は文脈を踏まえて考察してもかまいませんが、推測であることを明記し、事実と混同しないでください。
advisoriesに「未集計の疑い」が表示された場合は、解説を書く前に指示に従って集計してください。そのままでは、引用する極値や平均値が行単位の値であり、該当ディメンション全体の値ではないため、結論を誤る可能性があります(実例:月×地域の明細を折れ線グラフにした場合、plot_statsに「6月の最高値は156」と表示されても、実際には華東の1地域の値にすぎません)。
詳細な規範と例については REFERENCE.md を参照してください。