[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EVE1CWCWTQRZ0F5SD8DWC1":3,"skill-same:01M6EVE1CWCWTQRZ0F5SD8DWC1":87},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":31,"publishedAt":52,"linkOnly":53,"markdownContent":54,"markdownBody":55,"frontMatter":56,"refName":58,"commitSha":59,"skillDirectory":60,"forksCount":61,"repositoryHtmlUrl":62,"repositoryHomepageUrl":63,"ownerHtmlUrl":64,"ownerBlogUrl":6,"ownerDescription":65,"updatedAt":66,"install":67,"resources":80},"01M6EVE1CWCWTQRZ0F5SD8DWC1","data-visualization",null,"Data visualization with chart selection, color theory, and annotation best practices. Covers chart types (bar, line, scatter, heatmap), axes rules, and storytelling with data. Use for: charts, graphs, dashboards, reports, presentations, infographics, data stories. Triggers: data visualization, chart, graph, data chart, bar chart, line chart, scatter plot, data viz, visualization, dashboard chart, infographic data, data presentation, chart design, plot, heatmap, pie chart alternative","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Finference-sh-9\u002Fdata-visualization\u002FSKILL.md",[18,23,26],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000013","分析与可视化","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":27,"categoryName":28,"taxonomyType":29,"taxonomyTypeDesc":30},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51],"data visualization","visualization","data","reports","presentation","types","color","annotation","line","chart","data viz","infographic","selection","design","dashboards","Bash","Charts","graph","presentations","dashboard","2026-11-10 10:12:30",false,"---\nname: data-visualization\ndescription: \"Data visualization with chart selection, color theory, and annotation best practices. Covers chart types (bar, line, scatter, heatmap), axes rules, and storytelling with data. Use for: charts, graphs, dashboards, reports, presentations, infographics, data stories. Triggers: data visualization, chart, graph, data chart, bar chart, line chart, scatter plot, data viz, visualization, dashboard chart, infographic data, data presentation, chart design, plot, heatmap, pie chart alternative\"\nallowed-tools: Bash(infsh *)\n---\n\n# Data Visualization\n\nCreate clear, effective data visualizations via [inference.sh](https:\u002F\u002Finference.sh) CLI.\n\n## Quick Start\n\n```bash\ncurl -fsSL https:\u002F\u002Fcli.inference.sh | sh && infsh login\n\n# Generate a chart with Python\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\nmonths = [\\\"Jan\\\", \\\"Feb\\\", \\\"Mar\\\", \\\"Apr\\\", \\\"May\\\", \\\"Jun\\\"]\\nrevenue = [42, 48, 55, 61, 72, 89]\\n\\nfig, ax = plt.subplots(figsize=(10, 6))\\nax.bar(months, revenue, color=\\\"#3b82f6\\\", width=0.6)\\nax.set_ylabel(\\\"Revenue ($K)\\\")\\nax.set_title(\\\"Monthly Revenue Growth\\\", fontweight=\\\"bold\\\")\\nfor i, v in enumerate(revenue):\\n    ax.text(i, v + 1, f\\\"${v}K\\\", ha=\\\"center\\\", fontweight=\\\"bold\\\")\\nplt.tight_layout()\\nplt.savefig(\\\"revenue.png\\\", dpi=150)\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n> **Install note:** The [install script](https:\u002F\u002Fcli.inference.sh) only detects your OS\u002Farchitecture, downloads the matching binary from `dist.inference.sh`, and verifies its SHA-256 checksum. No elevated permissions or background processes. [Manual install & verification](https:\u002F\u002Fdist.inference.sh\u002Fcli\u002Fchecksums.txt) available.\n\n## Chart Selection Guide\n\n### Which Chart for Which Data?\n\n| Data Relationship | Best Chart | Never Use |\n|------------------|-----------|-----------|\n| **Change over time** | Line chart | Pie chart |\n| **Comparing categories** | Bar chart (horizontal for many categories) | Line chart |\n| **Part of a whole** | Stacked bar, treemap | Pie chart (controversial but: bar is always clearer) |\n| **Distribution** | Histogram, box plot | Bar chart |\n| **Correlation** | Scatter plot | Bar chart |\n| **Ranking** | Horizontal bar chart | Vertical bar, pie |\n| **Geographic** | Choropleth map | Bar chart |\n| **Composition over time** | Stacked area chart | Multiple pie charts |\n| **Single metric** | Big number (KPI card) | Any chart (overkill) |\n| **Flow \u002F process** | Sankey diagram | Bar chart |\n\n### The Pie Chart Problem\n\nPie charts are almost always the wrong choice:\n\n```\n❌ Pie chart problems:\n   - Hard to compare similar-sized slices\n   - Can't show more than 5-6 categories\n   - 3D pie charts are always wrong\n   - Impossible to read exact values\n\n✅ Use instead:\n   - Horizontal bar chart (easy comparison)\n   - Stacked bar (part of whole)\n   - Treemap (hierarchical parts)\n   - Just a table (if precision matters)\n```\n\n## Design Rules\n\n### Axes\n\n| Rule | Why |\n|------|-----|\n| Always start Y-axis at 0 (bar charts) | Prevents misleading visual |\n| Line charts CAN start above 0 | When showing change, not absolute values |\n| Label both axes | Reader shouldn't have to guess units |\n| Remove unnecessary gridlines | Reduce visual noise |\n| Use horizontal labels | Vertical text is hard to read |\n| Sort bar charts by value | Don't use alphabetical order unless there's a reason |\n\n### Color\n\n| Principle | Application |\n|-----------|------------|\n| **Max 5-7 colors** per chart | More becomes unreadable |\n| **Highlight one thing** | Grey everything else, color the focus |\n| **Sequential** for magnitude | Light → dark for low → high |\n| **Diverging** for positive\u002Fnegative | Red ← neutral → blue |\n| **Categorical** for groups | Distinct hues, similar brightness |\n| **Colorblind-safe** | Avoid red\u002Fgreen only — add shapes or labels |\n| **Consistent meaning** | If blue = revenue, keep it blue everywhere |\n\n### Good Color Palettes\n\n```python\n# Sequential (low to high)\nsequential = [\"#eff6ff\", \"#bfdbfe\", \"#60a5fa\", \"#2563eb\", \"#1d4ed8\"]\n\n# Diverging (negative to positive)\ndiverging = [\"#ef4444\", \"#f87171\", \"#d1d5db\", \"#34d399\", \"#10b981\"]\n\n# Categorical (distinct groups)\ncategorical = [\"#3b82f6\", \"#f59e0b\", \"#10b981\", \"#8b5cf6\", \"#ef4444\"]\n\n# Colorblind-safe\ncb_safe = [\"#0077BB\", \"#33BBEE\", \"#009988\", \"#EE7733\", \"#CC3311\"]\n```\n\n### Text and Labels\n\n| Element | Rule |\n|---------|------|\n| **Title** | States the insight, not the data type. \"Revenue doubled in Q2\" not \"Q2 Revenue Chart\" |\n| **Annotations** | Call out key data points directly on the chart |\n| **Legend** | Avoid if possible — label directly on chart lines\u002Fbars |\n| **Font size** | Minimum 12px, 14px+ for presentations |\n| **Number format** | Use K, M, B for large numbers (42K not 42,000) |\n| **Data labels** | Add to bars\u002Fpoints when exact values matter |\n\n## Chart Recipes\n\n### Line Chart (Time Series)\n\n```bash\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\nfig, ax = plt.subplots(figsize=(12, 6))\\nfig.patch.set_facecolor(\\\"white\\\")\\n\\nmonths = [\\\"Jan\\\", \\\"Feb\\\", \\\"Mar\\\", \\\"Apr\\\", \\\"May\\\", \\\"Jun\\\", \\\"Jul\\\", \\\"Aug\\\", \\\"Sep\\\", \\\"Oct\\\", \\\"Nov\\\", \\\"Dec\\\"]\\nthis_year = [120, 135, 148, 162, 178, 195, 210, 228, 245, 268, 290, 320]\\nlast_year = [95, 102, 108, 115, 122, 130, 138, 145, 155, 165, 178, 190]\\n\\nax.plot(months, this_year, color=\\\"#3b82f6\\\", linewidth=2.5, marker=\\\"o\\\", markersize=6, label=\\\"2024\\\")\\nax.plot(months, last_year, color=\\\"#94a3b8\\\", linewidth=2, linestyle=\\\"--\\\", label=\\\"2023\\\")\\nax.fill_between(range(len(months)), last_year, this_year, alpha=0.1, color=\\\"#3b82f6\\\")\\n\\nax.annotate(\\\"$320K\\\", xy=(11, 320), fontsize=14, fontweight=\\\"bold\\\", color=\\\"#3b82f6\\\")\\nax.annotate(\\\"$190K\\\", xy=(11, 190), fontsize=12, color=\\\"#94a3b8\\\")\\n\\nax.set_ylabel(\\\"Revenue ($K)\\\", fontsize=12)\\nax.set_title(\\\"Revenue grew 68% year-over-year\\\", fontsize=16, fontweight=\\\"bold\\\")\\nax.legend(fontsize=12)\\nax.spines[\\\"top\\\"].set_visible(False)\\nax.spines[\\\"right\\\"].set_visible(False)\\nax.grid(axis=\\\"y\\\", alpha=0.3)\\nplt.tight_layout()\\nplt.savefig(\\\"line-chart.png\\\", dpi=150)\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n### Horizontal Bar Chart (Comparison)\n\n```bash\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\nfig, ax = plt.subplots(figsize=(10, 6))\\n\\ncategories = [\\\"Email\\\", \\\"Social\\\", \\\"SEO\\\", \\\"Paid Ads\\\", \\\"Referral\\\", \\\"Direct\\\"]\\nvalues = [12, 18, 35, 22, 8, 5]\\ncolors = [\\\"#94a3b8\\\"] * len(values)\\ncolors[2] = \\\"#3b82f6\\\"  # Highlight the winner\\n\\n# Sort by value\\nsorted_pairs = sorted(zip(values, categories, colors))\\nvalues, categories, colors = zip(*sorted_pairs)\\n\\nax.barh(categories, values, color=colors, height=0.6)\\nfor i, v in enumerate(values):\\n    ax.text(v + 0.5, i, f\\\"{v}%\\\", va=\\\"center\\\", fontsize=12, fontweight=\\\"bold\\\")\\n\\nax.set_xlabel(\\\"% of Total Traffic\\\", fontsize=12)\\nax.set_title(\\\"SEO drives the most traffic\\\", fontsize=16, fontweight=\\\"bold\\\")\\nax.spines[\\\"top\\\"].set_visible(False)\\nax.spines[\\\"right\\\"].set_visible(False)\\nplt.tight_layout()\\nplt.savefig(\\\"bar-chart.png\\\", dpi=150)\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n### KPI \u002F Big Number Card\n\n```bash\ninfsh app run infsh\u002Fhtml-to-image --input '{\n  \"html\": \"\u003Cdiv style=\\\"display:flex;gap:20px;padding:20px;background:white;font-family:system-ui\\\">\u003Cdiv style=\\\"background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:24px;width:200px;text-align:center\\\">\u003Cp style=\\\"color:#64748b;font-size:14px;margin:0\\\">Monthly Revenue\u003C\u002Fp>\u003Cp style=\\\"font-size:48px;font-weight:900;margin:8px 0;color:#1e293b\\\">$89K\u003C\u002Fp>\u003Cp style=\\\"color:#22c55e;font-size:14px;margin:0\\\">↑ 23% vs last month\u003C\u002Fp>\u003C\u002Fdiv>\u003Cdiv style=\\\"background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:24px;width:200px;text-align:center\\\">\u003Cp style=\\\"color:#64748b;font-size:14px;margin:0\\\">Active Users\u003C\u002Fp>\u003Cp style=\\\"font-size:48px;font-weight:900;margin:8px 0;color:#1e293b\\\">12.4K\u003C\u002Fp>\u003Cp style=\\\"color:#22c55e;font-size:14px;margin:0\\\">↑ 8% vs last month\u003C\u002Fp>\u003C\u002Fdiv>\u003Cdiv style=\\\"background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:24px;width:200px;text-align:center\\\">\u003Cp style=\\\"color:#64748b;font-size:14px;margin:0\\\">Churn Rate\u003C\u002Fp>\u003Cp style=\\\"font-size:48px;font-weight:900;margin:8px 0;color:#1e293b\\\">2.1%\u003C\u002Fp>\u003Cp style=\\\"color:#ef4444;font-size:14px;margin:0\\\">↑ 0.3% vs last month\u003C\u002Fp>\u003C\u002Fdiv>\u003C\u002Fdiv>\"\n}'\n```\n\n### Heatmap\n\n```bash\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport numpy as np\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\nfig, ax = plt.subplots(figsize=(10, 6))\\n\\ndays = [\\\"Mon\\\", \\\"Tue\\\", \\\"Wed\\\", \\\"Thu\\\", \\\"Fri\\\", \\\"Sat\\\", \\\"Sun\\\"]\\nhours = [\\\"9AM\\\", \\\"10AM\\\", \\\"11AM\\\", \\\"12PM\\\", \\\"1PM\\\", \\\"2PM\\\", \\\"3PM\\\", \\\"4PM\\\", \\\"5PM\\\"]\\ndata = np.random.randint(10, 100, size=(len(hours), len(days)))\\ndata[2][1] = 95  # Tuesday 11AM peak\\ndata[2][3] = 88  # Thursday 11AM\\n\\nim = ax.imshow(data, cmap=\\\"Blues\\\", aspect=\\\"auto\\\")\\nax.set_xticks(range(len(days)))\\nax.set_yticks(range(len(hours)))\\nax.set_xticklabels(days, fontsize=12)\\nax.set_yticklabels(hours, fontsize=12)\\n\\nfor i in range(len(hours)):\\n    for j in range(len(days)):\\n        color = \\\"white\\\" if data[i][j] > 60 else \\\"black\\\"\\n        ax.text(j, i, data[i][j], ha=\\\"center\\\", va=\\\"center\\\", fontsize=10, color=color)\\n\\nax.set_title(\\\"Website Traffic by Day & Hour\\\", fontsize=16, fontweight=\\\"bold\\\")\\nplt.colorbar(im, label=\\\"Visitors\\\")\\nplt.tight_layout()\\nplt.savefig(\\\"heatmap.png\\\", dpi=150)\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n## Storytelling with Data\n\n### The Narrative Arc\n\n| Step | What to Do | Example |\n|------|-----------|---------|\n| 1. **Context** | Set up what the reader needs to know | \"We track customer acquisition cost monthly\" |\n| 2. **Tension** | Show the problem or change | \"CAC increased 40% in Q3\" |\n| 3. **Resolution** | Show the insight or solution | \"But LTV increased 80%, so unit economics improved\" |\n\n### Title as Insight\n\n```\n❌ Descriptive titles (what the chart shows):\n   \"Q3 Revenue by Product Line\"\n   \"Monthly Active Users 2024\"\n   \"Customer Satisfaction Survey Results\"\n\n✅ Insight titles (what the chart means):\n   \"Enterprise product drives 70% of revenue growth\"\n   \"User growth accelerated after the free tier launch\"\n   \"Support response time is the #1 satisfaction driver\"\n```\n\n### Annotation Techniques\n\n| Technique | When to Use |\n|-----------|------------|\n| **Call-out label** | Highlight a specific data point (\"Peak: 320K\") |\n| **Reference line** | Show target\u002Fbenchmark (\"Goal: 100K\") |\n| **Shaded region** | Mark a time period (\"Product launch window\") |\n| **Arrow + text** | Draw attention to trend change |\n| **Before\u002Fafter line** | Show impact of an event |\n\n## Dark Mode Charts\n\n```bash\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\n# Dark theme\\nplt.rcParams.update({\\n    \\\"figure.facecolor\\\": \\\"#0f172a\\\",\\n    \\\"axes.facecolor\\\": \\\"#0f172a\\\",\\n    \\\"axes.edgecolor\\\": \\\"#334155\\\",\\n    \\\"axes.labelcolor\\\": \\\"white\\\",\\n    \\\"text.color\\\": \\\"white\\\",\\n    \\\"xtick.color\\\": \\\"white\\\",\\n    \\\"ytick.color\\\": \\\"white\\\",\\n    \\\"grid.color\\\": \\\"#1e293b\\\"\\n})\\n\\nfig, ax = plt.subplots(figsize=(12, 6))\\nmonths = [\\\"Jan\\\", \\\"Feb\\\", \\\"Mar\\\", \\\"Apr\\\", \\\"May\\\", \\\"Jun\\\"]\\nvalues = [45, 52, 58, 72, 85, 98]\\n\\nax.plot(months, values, color=\\\"#818cf8\\\", linewidth=3, marker=\\\"o\\\", markersize=8)\\nax.fill_between(range(len(months)), values, alpha=0.15, color=\\\"#818cf8\\\")\\nax.set_title(\\\"MRR Growth: On track for $100K\\\", fontsize=18, fontweight=\\\"bold\\\")\\nax.set_ylabel(\\\"MRR ($K)\\\", fontsize=13)\\nax.spines[\\\"top\\\"].set_visible(False)\\nax.spines[\\\"right\\\"].set_visible(False)\\nax.grid(axis=\\\"y\\\", alpha=0.2)\\n\\nfor i, v in enumerate(values):\\n    ax.annotate(f\\\"${v}K\\\", (i, v), textcoords=\\\"offset points\\\", xytext=(0, 12), ha=\\\"center\\\", fontsize=11, fontweight=\\\"bold\\\")\\n\\nplt.tight_layout()\\nplt.savefig(\\\"dark-chart.png\\\", dpi=150, facecolor=\\\"#0f172a\\\")\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n## Common Mistakes\n\n| Mistake | Problem | Fix |\n|---------|---------|-----|\n| Pie charts | Hard to compare, always misleading | Use bar charts or treemaps |\n| Y-axis not starting at 0 (bar charts) | Exaggerates differences | Start at 0 for bars, OK to truncate for lines |\n| Too many colors | Visual noise, confusing | Max 5-7 colors, highlight only what matters |\n| No title or generic title | Reader doesn't know the insight | Title = the takeaway, not the data type |\n| 3D charts | Distorts data, looks unprofessional | Always use 2D |\n| Dual Y-axes | Misleading, hard to read | Use two separate charts |\n| Alphabetical sort on bar charts | Hides the story | Sort by value (largest first) |\n| No labels on axes | Reader can't interpret | Always label with units |\n| Chartjunk (decorative elements) | Distracts from data | Remove everything that doesn't convey information |\n| Red\u002Fgreen only for color coding | Colorblind users can't read | Use shapes, patterns, or colorblind-safe palettes |\n\n## Related Skills\n\n```bash\nnpx skills add inference-sh\u002Fskills@pitch-deck-visuals\nnpx skills add inference-sh\u002Fskills@technical-blog-writing\nnpx skills add inference-sh\u002Fskills@competitor-teardown\n```\n\nBrowse all apps: `infsh app list`\n","# Data Visualization\n\nCreate clear, effective data visualizations via [inference.sh](https:\u002F\u002Finference.sh) CLI.\n\n## Quick Start\n\n```bash\ncurl -fsSL https:\u002F\u002Fcli.inference.sh | sh && infsh login\n\n# Generate a chart with Python\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\nmonths = [\\\"Jan\\\", \\\"Feb\\\", \\\"Mar\\\", \\\"Apr\\\", \\\"May\\\", \\\"Jun\\\"]\\nrevenue = [42, 48, 55, 61, 72, 89]\\n\\nfig, ax = plt.subplots(figsize=(10, 6))\\nax.bar(months, revenue, color=\\\"#3b82f6\\\", width=0.6)\\nax.set_ylabel(\\\"Revenue ($K)\\\")\\nax.set_title(\\\"Monthly Revenue Growth\\\", fontweight=\\\"bold\\\")\\nfor i, v in enumerate(revenue):\\n    ax.text(i, v + 1, f\\\"${v}K\\\", ha=\\\"center\\\", fontweight=\\\"bold\\\")\\nplt.tight_layout()\\nplt.savefig(\\\"revenue.png\\\", dpi=150)\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n> **Install note:** The [install script](https:\u002F\u002Fcli.inference.sh) only detects your OS\u002Farchitecture, downloads the matching binary from `dist.inference.sh`, and verifies its SHA-256 checksum. No elevated permissions or background processes. [Manual install & verification](https:\u002F\u002Fdist.inference.sh\u002Fcli\u002Fchecksums.txt) available.\n\n## Chart Selection Guide\n\n### Which Chart for Which Data?\n\n| Data Relationship | Best Chart | Never Use |\n|------------------|-----------|-----------|\n| **Change over time** | Line chart | Pie chart |\n| **Comparing categories** | Bar chart (horizontal for many categories) | Line chart |\n| **Part of a whole** | Stacked bar, treemap | Pie chart (controversial but: bar is always clearer) |\n| **Distribution** | Histogram, box plot | Bar chart |\n| **Correlation** | Scatter plot | Bar chart |\n| **Ranking** | Horizontal bar chart | Vertical bar, pie |\n| **Geographic** | Choropleth map | Bar chart |\n| **Composition over time** | Stacked area chart | Multiple pie charts |\n| **Single metric** | Big number (KPI card) | Any chart (overkill) |\n| **Flow \u002F process** | Sankey diagram | Bar chart |\n\n### The Pie Chart Problem\n\nPie charts are almost always the wrong choice:\n\n```\n❌ Pie chart problems:\n   - Hard to compare similar-sized slices\n   - Can't show more than 5-6 categories\n   - 3D pie charts are always wrong\n   - Impossible to read exact values\n\n✅ Use instead:\n   - Horizontal bar chart (easy comparison)\n   - Stacked bar (part of whole)\n   - Treemap (hierarchical parts)\n   - Just a table (if precision matters)\n```\n\n## Design Rules\n\n### Axes\n\n| Rule | Why |\n|------|-----|\n| Always start Y-axis at 0 (bar charts) | Prevents misleading visual |\n| Line charts CAN start above 0 | When showing change, not absolute values |\n| Label both axes | Reader shouldn't have to guess units |\n| Remove unnecessary gridlines | Reduce visual noise |\n| Use horizontal labels | Vertical text is hard to read |\n| Sort bar charts by value | Don't use alphabetical order unless there's a reason |\n\n### Color\n\n| Principle | Application |\n|-----------|------------|\n| **Max 5-7 colors** per chart | More becomes unreadable |\n| **Highlight one thing** | Grey everything else, color the focus |\n| **Sequential** for magnitude | Light → dark for low → high |\n| **Diverging** for positive\u002Fnegative | Red ← neutral → blue |\n| **Categorical** for groups | Distinct hues, similar brightness |\n| **Colorblind-safe** | Avoid red\u002Fgreen only — add shapes or labels |\n| **Consistent meaning** | If blue = revenue, keep it blue everywhere |\n\n### Good Color Palettes\n\n```python\n# Sequential (low to high)\nsequential = [\"#eff6ff\", \"#bfdbfe\", \"#60a5fa\", \"#2563eb\", \"#1d4ed8\"]\n\n# Diverging (negative to positive)\ndiverging = [\"#ef4444\", \"#f87171\", \"#d1d5db\", \"#34d399\", \"#10b981\"]\n\n# Categorical (distinct groups)\ncategorical = [\"#3b82f6\", \"#f59e0b\", \"#10b981\", \"#8b5cf6\", \"#ef4444\"]\n\n# Colorblind-safe\ncb_safe = [\"#0077BB\", \"#33BBEE\", \"#009988\", \"#EE7733\", \"#CC3311\"]\n```\n\n### Text and Labels\n\n| Element | Rule |\n|---------|------|\n| **Title** | States the insight, not the data type. \"Revenue doubled in Q2\" not \"Q2 Revenue Chart\" |\n| **Annotations** | Call out key data points directly on the chart |\n| **Legend** | Avoid if possible — label directly on chart lines\u002Fbars |\n| **Font size** | Minimum 12px, 14px+ for presentations |\n| **Number format** | Use K, M, B for large numbers (42K not 42,000) |\n| **Data labels** | Add to bars\u002Fpoints when exact values matter |\n\n## Chart Recipes\n\n### Line Chart (Time Series)\n\n```bash\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\nfig, ax = plt.subplots(figsize=(12, 6))\\nfig.patch.set_facecolor(\\\"white\\\")\\n\\nmonths = [\\\"Jan\\\", \\\"Feb\\\", \\\"Mar\\\", \\\"Apr\\\", \\\"May\\\", \\\"Jun\\\", \\\"Jul\\\", \\\"Aug\\\", \\\"Sep\\\", \\\"Oct\\\", \\\"Nov\\\", \\\"Dec\\\"]\\nthis_year = [120, 135, 148, 162, 178, 195, 210, 228, 245, 268, 290, 320]\\nlast_year = [95, 102, 108, 115, 122, 130, 138, 145, 155, 165, 178, 190]\\n\\nax.plot(months, this_year, color=\\\"#3b82f6\\\", linewidth=2.5, marker=\\\"o\\\", markersize=6, label=\\\"2024\\\")\\nax.plot(months, last_year, color=\\\"#94a3b8\\\", linewidth=2, linestyle=\\\"--\\\", label=\\\"2023\\\")\\nax.fill_between(range(len(months)), last_year, this_year, alpha=0.1, color=\\\"#3b82f6\\\")\\n\\nax.annotate(\\\"$320K\\\", xy=(11, 320), fontsize=14, fontweight=\\\"bold\\\", color=\\\"#3b82f6\\\")\\nax.annotate(\\\"$190K\\\", xy=(11, 190), fontsize=12, color=\\\"#94a3b8\\\")\\n\\nax.set_ylabel(\\\"Revenue ($K)\\\", fontsize=12)\\nax.set_title(\\\"Revenue grew 68% year-over-year\\\", fontsize=16, fontweight=\\\"bold\\\")\\nax.legend(fontsize=12)\\nax.spines[\\\"top\\\"].set_visible(False)\\nax.spines[\\\"right\\\"].set_visible(False)\\nax.grid(axis=\\\"y\\\", alpha=0.3)\\nplt.tight_layout()\\nplt.savefig(\\\"line-chart.png\\\", dpi=150)\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n### Horizontal Bar Chart (Comparison)\n\n```bash\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\nfig, ax = plt.subplots(figsize=(10, 6))\\n\\ncategories = [\\\"Email\\\", \\\"Social\\\", \\\"SEO\\\", \\\"Paid Ads\\\", \\\"Referral\\\", \\\"Direct\\\"]\\nvalues = [12, 18, 35, 22, 8, 5]\\ncolors = [\\\"#94a3b8\\\"] * len(values)\\ncolors[2] = \\\"#3b82f6\\\"  # Highlight the winner\\n\\n# Sort by value\\nsorted_pairs = sorted(zip(values, categories, colors))\\nvalues, categories, colors = zip(*sorted_pairs)\\n\\nax.barh(categories, values, color=colors, height=0.6)\\nfor i, v in enumerate(values):\\n    ax.text(v + 0.5, i, f\\\"{v}%\\\", va=\\\"center\\\", fontsize=12, fontweight=\\\"bold\\\")\\n\\nax.set_xlabel(\\\"% of Total Traffic\\\", fontsize=12)\\nax.set_title(\\\"SEO drives the most traffic\\\", fontsize=16, fontweight=\\\"bold\\\")\\nax.spines[\\\"top\\\"].set_visible(False)\\nax.spines[\\\"right\\\"].set_visible(False)\\nplt.tight_layout()\\nplt.savefig(\\\"bar-chart.png\\\", dpi=150)\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n### KPI \u002F Big Number Card\n\n```bash\ninfsh app run infsh\u002Fhtml-to-image --input '{\n  \"html\": \"\u003Cdiv style=\\\"display:flex;gap:20px;padding:20px;background:white;font-family:system-ui\\\">\u003Cdiv style=\\\"background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:24px;width:200px;text-align:center\\\">\u003Cp style=\\\"color:#64748b;font-size:14px;margin:0\\\">Monthly Revenue\u003C\u002Fp>\u003Cp style=\\\"font-size:48px;font-weight:900;margin:8px 0;color:#1e293b\\\">$89K\u003C\u002Fp>\u003Cp style=\\\"color:#22c55e;font-size:14px;margin:0\\\">↑ 23% vs last month\u003C\u002Fp>\u003C\u002Fdiv>\u003Cdiv style=\\\"background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:24px;width:200px;text-align:center\\\">\u003Cp style=\\\"color:#64748b;font-size:14px;margin:0\\\">Active Users\u003C\u002Fp>\u003Cp style=\\\"font-size:48px;font-weight:900;margin:8px 0;color:#1e293b\\\">12.4K\u003C\u002Fp>\u003Cp style=\\\"color:#22c55e;font-size:14px;margin:0\\\">↑ 8% vs last month\u003C\u002Fp>\u003C\u002Fdiv>\u003Cdiv style=\\\"background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:24px;width:200px;text-align:center\\\">\u003Cp style=\\\"color:#64748b;font-size:14px;margin:0\\\">Churn Rate\u003C\u002Fp>\u003Cp style=\\\"font-size:48px;font-weight:900;margin:8px 0;color:#1e293b\\\">2.1%\u003C\u002Fp>\u003Cp style=\\\"color:#ef4444;font-size:14px;margin:0\\\">↑ 0.3% vs last month\u003C\u002Fp>\u003C\u002Fdiv>\u003C\u002Fdiv>\"\n}'\n```\n\n### Heatmap\n\n```bash\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport numpy as np\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\nfig, ax = plt.subplots(figsize=(10, 6))\\n\\ndays = [\\\"Mon\\\", \\\"Tue\\\", \\\"Wed\\\", \\\"Thu\\\", \\\"Fri\\\", \\\"Sat\\\", \\\"Sun\\\"]\\nhours = [\\\"9AM\\\", \\\"10AM\\\", \\\"11AM\\\", \\\"12PM\\\", \\\"1PM\\\", \\\"2PM\\\", \\\"3PM\\\", \\\"4PM\\\", \\\"5PM\\\"]\\ndata = np.random.randint(10, 100, size=(len(hours), len(days)))\\ndata[2][1] = 95  # Tuesday 11AM peak\\ndata[2][3] = 88  # Thursday 11AM\\n\\nim = ax.imshow(data, cmap=\\\"Blues\\\", aspect=\\\"auto\\\")\\nax.set_xticks(range(len(days)))\\nax.set_yticks(range(len(hours)))\\nax.set_xticklabels(days, fontsize=12)\\nax.set_yticklabels(hours, fontsize=12)\\n\\nfor i in range(len(hours)):\\n    for j in range(len(days)):\\n        color = \\\"white\\\" if data[i][j] > 60 else \\\"black\\\"\\n        ax.text(j, i, data[i][j], ha=\\\"center\\\", va=\\\"center\\\", fontsize=10, color=color)\\n\\nax.set_title(\\\"Website Traffic by Day & Hour\\\", fontsize=16, fontweight=\\\"bold\\\")\\nplt.colorbar(im, label=\\\"Visitors\\\")\\nplt.tight_layout()\\nplt.savefig(\\\"heatmap.png\\\", dpi=150)\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n## Storytelling with Data\n\n### The Narrative Arc\n\n| Step | What to Do | Example |\n|------|-----------|---------|\n| 1. **Context** | Set up what the reader needs to know | \"We track customer acquisition cost monthly\" |\n| 2. **Tension** | Show the problem or change | \"CAC increased 40% in Q3\" |\n| 3. **Resolution** | Show the insight or solution | \"But LTV increased 80%, so unit economics improved\" |\n\n### Title as Insight\n\n```\n❌ Descriptive titles (what the chart shows):\n   \"Q3 Revenue by Product Line\"\n   \"Monthly Active Users 2024\"\n   \"Customer Satisfaction Survey Results\"\n\n✅ Insight titles (what the chart means):\n   \"Enterprise product drives 70% of revenue growth\"\n   \"User growth accelerated after the free tier launch\"\n   \"Support response time is the #1 satisfaction driver\"\n```\n\n### Annotation Techniques\n\n| Technique | When to Use |\n|-----------|------------|\n| **Call-out label** | Highlight a specific data point (\"Peak: 320K\") |\n| **Reference line** | Show target\u002Fbenchmark (\"Goal: 100K\") |\n| **Shaded region** | Mark a time period (\"Product launch window\") |\n| **Arrow + text** | Draw attention to trend change |\n| **Before\u002Fafter line** | Show impact of an event |\n\n## Dark Mode Charts\n\n```bash\ninfsh app run infsh\u002Fpython-executor --input '{\n  \"code\": \"import matplotlib.pyplot as plt\\nimport matplotlib\\nmatplotlib.use(\\\"Agg\\\")\\n\\n# Dark theme\\nplt.rcParams.update({\\n    \\\"figure.facecolor\\\": \\\"#0f172a\\\",\\n    \\\"axes.facecolor\\\": \\\"#0f172a\\\",\\n    \\\"axes.edgecolor\\\": \\\"#334155\\\",\\n    \\\"axes.labelcolor\\\": \\\"white\\\",\\n    \\\"text.color\\\": \\\"white\\\",\\n    \\\"xtick.color\\\": \\\"white\\\",\\n    \\\"ytick.color\\\": \\\"white\\\",\\n    \\\"grid.color\\\": \\\"#1e293b\\\"\\n})\\n\\nfig, ax = plt.subplots(figsize=(12, 6))\\nmonths = [\\\"Jan\\\", \\\"Feb\\\", \\\"Mar\\\", \\\"Apr\\\", \\\"May\\\", \\\"Jun\\\"]\\nvalues = [45, 52, 58, 72, 85, 98]\\n\\nax.plot(months, values, color=\\\"#818cf8\\\", linewidth=3, marker=\\\"o\\\", markersize=8)\\nax.fill_between(range(len(months)), values, alpha=0.15, color=\\\"#818cf8\\\")\\nax.set_title(\\\"MRR Growth: On track for $100K\\\", fontsize=18, fontweight=\\\"bold\\\")\\nax.set_ylabel(\\\"MRR ($K)\\\", fontsize=13)\\nax.spines[\\\"top\\\"].set_visible(False)\\nax.spines[\\\"right\\\"].set_visible(False)\\nax.grid(axis=\\\"y\\\", alpha=0.2)\\n\\nfor i, v in enumerate(values):\\n    ax.annotate(f\\\"${v}K\\\", (i, v), textcoords=\\\"offset points\\\", xytext=(0, 12), ha=\\\"center\\\", fontsize=11, fontweight=\\\"bold\\\")\\n\\nplt.tight_layout()\\nplt.savefig(\\\"dark-chart.png\\\", dpi=150, facecolor=\\\"#0f172a\\\")\\nprint(\\\"Saved\\\")\"\n}'\n```\n\n## Common Mistakes\n\n| Mistake | Problem | Fix |\n|---------|---------|-----|\n| Pie charts | Hard to compare, always misleading | Use bar charts or treemaps |\n| Y-axis not starting at 0 (bar charts) | Exaggerates differences | Start at 0 for bars, OK to truncate for lines |\n| Too many colors | Visual noise, confusing | Max 5-7 colors, highlight only what matters |\n| No title or generic title | Reader doesn't know the insight | Title = the takeaway, not the data type |\n| 3D charts | Distorts data, looks unprofessional | Always use 2D |\n| Dual Y-axes | Misleading, hard to read | Use two separate charts |\n| Alphabetical sort on bar charts | Hides the story | Sort by value (largest first) |\n| No labels on axes | Reader can't interpret | Always label with units |\n| Chartjunk (decorative elements) | Distracts from data | Remove everything that doesn't convey information |\n| Red\u002Fgreen only for color coding | Colorblind users can't read | Use shapes, patterns, or colorblind-safe palettes |\n\n## Related Skills\n\n```bash\nnpx skills add inference-sh\u002Fskills@pitch-deck-visuals\nnpx skills add inference-sh\u002Fskills@technical-blog-writing\nnpx skills add inference-sh\u002Fskills@competitor-teardown\n```\n\nBrowse all apps: `infsh app list`\n",{"name":5,"description":7,"allowed-tools":57},"Bash(infsh *)","main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002Finference-sh-9\u002Fdata-visualization",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":68,"prompt":78,"zipAvailable":79},[69,72,75],{"tool":70,"command":71},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill data-visualization",{"tool":73,"command":74},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill data-visualization",{"tool":76,"command":77},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill data-visualization","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Finference-sh-9\u002Fdata-visualization\u002FSKILL.md",true,[81],{"path":82,"resourceType":83,"resourceTypeDesc":84,"sizeBytes":85,"sourceHtmlUrl":86},"skill-report.json","REFERENCE","参考文档",10042,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Finference-sh-9\u002Fdata-visualization\u002Fskill-report.json",[88,100,110,119,125,132],{"skillNo":89,"name":90,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":96,"publishedAt":52},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[93],{"categoryNo":94,"categoryName":95,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[97,98,99],"model","model hierarchy","model hierarchy skill",{"skillNo":101,"name":102,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":106,"publishedAt":52},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[105],{"categoryNo":94,"categoryName":95,"taxonomyType":21,"taxonomyTypeDesc":22},[107,108,109],"MCP","zoom","zoom mcp",{"skillNo":111,"name":112,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":115,"publishedAt":52},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[116,117,118,108],"sdk","zoom apps sdk","apps",{"skillNo":120,"name":121,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":122,"categories":123,"keywords":124,"publishedAt":52},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[121],{"skillNo":126,"name":127,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":128,"categories":129,"keywords":131,"publishedAt":52},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[130],{"categoryNo":94,"categoryName":95,"taxonomyType":21,"taxonomyTypeDesc":22},[127],{"skillNo":133,"name":134,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":135,"categories":136,"keywords":137,"publishedAt":52},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[134]]