文档

Chart Generator

试用

Data visualization chart generator. Use when user needs to create charts from data for reports, presentations, or documents. Supports bar, line, pie, scatter...

它能做什么

Professional data visualization chart generator for reports, presentations, and documents.

技能文档

Chart Generator

Professional data visualization chart generator for reports, presentations, and documents.

Features

  • 📊 Multiple Chart Types: Bar, line, pie, scatter, radar, area, stacked
  • 📁 Multiple Data Sources: CSV, Excel, JSON, manual, web, document extraction
  • 🎨 Professional Styling: Clean, publication-ready charts with custom options
  • 📐 Flexible Output: PNG, SVG, PDF, Word, Excel, Markdown, HTML
  • 🔗 Embed Support: Direct embedding into documents
  • 🌍 Multi-Language: Chinese, English, Japanese, Korean (no encoding issues)
  • ✅ Cross-Platform: Windows, macOS, Linux

Supported Chart Types

TypeUse CaseBest For
Bar ChartCompare valuesSales, rankings
Line ChartShow trendsTime series, growth
Pie ChartShow proportionsMarket share, composition
Scatter PlotShow correlationData relationships
Radar ChartMulti-dimensionPerformance comparison
Area ChartCumulative valuesStacked data
Stacked BarCompositionMulti-category breakdown

Trigger Conditions

  • "帮我画图" / "Create a chart"
  • "生成柱状图" / "Generate bar chart"
  • "数据可视化" / "Data visualization"
  • "做一个趋势图" / "Make a trend chart"
  • "图表分析" / "Chart analysis"
  • "chart-generator"

Step 1: Understand Requirements

请提供以下信息:

图表类型:(柱状图/折线图/饼图/散点图/雷达图)
数据来源:(手动输入/CSV/Excel/JSON)
数据内容:
标题:
X轴标签:
Y轴标签:
输出格式:(PNG/SVG)
颜色要求:(默认/自定义)

Step 2: Generate Chart

Python Script Template

python3 << 'PYEOF'
import os
import matplotlib.pyplot as plt
import matplotlib
import pandas as pd
import numpy as np
from matplotlib import font_manager

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['Noto Sans SC', 'SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

class ChartGenerator:
    def __init__(self):
        self.fig = None
        self.ax = None
        
    def create_bar_chart(self, labels, values, title='', 
                         xlabel='', ylabel='', 
                         color='#3182ce', output_path=None):
        """Create bar chart"""
        self.fig, self.ax = plt.subplots(figsize=(10, 6))
        
        bars = self.ax.bar(labels, values, color=color, edgecolor='white', linewidth=0.5)
        
        # Add value labels on bars
        for bar in bars:
            height = bar.get_height()
            self.ax.text(bar.get_x() + bar.get_width()/2., height,
                        f'{height:,.0f}',
                        ha='center', va='bottom', fontsize=10)
        
        self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
        self.ax.set_xlabel(xlabel, fontsize=12)
        self.ax.set_ylabel(ylabel, fontsize=12)
        
        # Clean styling
        self.ax.spines['top'].set_visible(False)
        self.ax.spines['right'].set_visible(False)
        self.ax.grid(axis='y', alpha=0.3)
        
        plt.tight_layout()
        
        if output_path:
            self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
            plt.close()
            return output_path
        
        return self.fig
    
    def create_line_chart(self, x_data, y_data_list, labels=None,
                         title='', xlabel='', ylabel='',
                         colors=None, output_path=None):
        """Create line chart"""
        self.fig, self.ax = plt.subplots(figsize=(10, 6))
        
        if colors is None:
            colors = ['#3182ce', '#48bb78', '#ed8936', '#e53e3e', '#9f7aea']
        
        for i, y_data in enumerate(y_data_list):
            color = colors[i % len(colors)]
            label = labels[i] if labels and i < len(labels) else f'Series {i+1}'
            self.ax.plot(x_data, y_data, marker='o', linewidth=2, 
                        color=color, label=label, markersize=6)
        
        self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
        self.ax.set_xlabel(xlabel, fontsize=12)
        self.ax.set_ylabel(ylabel, fontsize=12)
        
        if labels:
            self.ax.legend(loc='best', framealpha=0.9)
        
        self.ax.spines['top'].set_visible(False)
        self.ax.spines['right'].set_visible(False)
        self.ax.grid(alpha=0.3)
        
        plt.tight_layout()
        
        if output_path:
            self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
            plt.close()
            return output_path
        
        return self.fig
    
    def create_pie_chart(self, labels, values, title='',
                        colors=None, output_path=None):
        """Create pie chart"""
        self.fig, self.ax = plt.subplots(figsize=(8, 8))
        
        if colors is None:
            colors = ['#3182ce', '#48bb78', '#ed8936', '#e53e3e', '#9f7aea',
                     '#38b2ac', '#d69e2e', '#667eea']
        
        wedges, texts, autotexts = self.ax.pie(
            values, labels=labels, colors=colors[:len(values)],
            autopct='%1.1f%%', startangle=90,
            textprops={'fontsize': 11}
        )
        
        for autotext in autotexts:
            autotext.set_color('white')
            autotext.set_fontweight('bold')
        
        self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
        
        plt.tight_layout()
        
        if output_path:
            self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
            plt.close()
            return output_path
        
        return self.fig
    
    def create_scatter_plot(self, x_data, y_data, title='',
                           xlabel='', ylabel='',
                           color='#3182ce', output_path=None):
        """Create scatter plot"""
        self.fig, self.ax = plt.subplots(figsize=(10, 6))
        
        self.ax.scatter(x_data, y_data, c=color, alpha=0.6, s=50)
        
        # Add trend line
        z = np.polyfit(x_data, y_data, 1)
        p = np.poly1d(z)
        self.ax.plot(x_data, p(x_data), '--', color='#e53e3e', alpha=0.8, label='Trend')
        
        self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
        self.ax.set_xlabel(xlabel, fontsize=12)
        self.ax.set_ylabel(ylabel, fontsize=12)
        self.ax.legend()
        
        self.ax.spines['top'].set_visible(False)
        self.ax.spines['right'].set_visible(False)
        self.ax.grid(alpha=0.3)
        
        plt.tight_layout()
        
        if output_path:
            self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
            plt.close()
            return output_path
        
        return self.fig
    
    def create_multi_bar_chart(self, labels, data_dict, title='',
                              xlabel='', ylabel='', output_path=None):
        """Create grouped bar chart"""
        self.fig, self.ax = plt.subplots(figsize=(12, 6))
        
        x = np.arange(len(labels))
        width = 0.8 / len(data_dict)
        
        colors = ['#3182ce', '#48bb78', '#ed8936', '#e53e3e', '#9f7aea']
        
        for i, (name, values) in enumerate(data_dict.items()):
            offset = (i - len(data_dict)/2 + 0.5) * width
            bars = self.ax.bar(x + offset, values, width, label=name,
                             color=colors[i % len(colors)], edgecolor='white')
        
        self.ax.set_title(title, fontsize=16, fontweight='bold', pad=20)
        self.ax.set_xlabel(xlabel, fontsize=12)
        self.ax.set_ylabel(ylabel, fontsize=12)
        self.ax.set_xticks(x)
        self.ax.set_xticklabels(labels)
        self.ax.legend()
        
        self.ax.spines['top'].set_visible(False)
        self.ax.spines['right'].set_visible(False)
        self.ax.grid(axis='y', alpha=0.3)
        
        plt.tight_layout()
        
        if output_path:
            self.fig.savefig(output_path, dpi=150, bbox_inches='tight')
            plt.close()
            return output_path
        
        return self.fig
    
    def load_from_csv(self, csv_path, x_col=None, y_cols=None):
        """Load data from CSV file"""
        df = pd.read_csv(csv_path)
        
        if x_col is None:
            x_col = df.columns[0]
        if y_cols is None:
            y_cols = [col for col in df.columns if col != x_col]
        
        return {
            'x': df[x_col].tolist(),
            'y': {col: df[col].tolist() for col in y_cols},
            'df': df
        }
    
    def load_from_excel(self, excel_path, sheet_name=0, x_col=None, y_cols=None):
        """Load data from Excel file"""
        df = pd.read_excel(excel_path, sheet_name=sheet_name)
        
        if x_col is None:
            x_col = df.columns[0]
        if y_cols is None:
            y_cols = [col for col in df.columns if col != x_col]
        
        return {
            'x': df[x_col].tolist(),
            'y': {col: df[col].tolist() for col in y_cols},
            'df': df
        }
    
    def load_from_json(self, json_path):
        """Load data from JSON file"""
        import json
        with open(json_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        return data
    
    def load_from_directory(self, dir_path, file_pattern='*.csv'):
        """Load and aggregate data from multiple files in directory"""
        import glob
        
        all_data = []
        for file_path in glob.glob(os.path.join(dir_path, file_pattern)):
            if file_path.endswith('.csv'):
                df = pd.read_csv(file_path)
            elif file_path.endswith('.xlsx'):
                df = pd.read_excel(file_path)
            else:
                continue
            df['source_file'] = os.path.basename(file_path)
            all_data.append(df)
        
        if all_data:
            return pd.concat(all_data, ignore_index=True)
        return pd.DataFrame()
    
    def extract_data_from_text(self, text):
        """Extract numerical data from text content"""
        import re
        
        # Find patterns like "Sales: 100" or "销售额:100万"
        patterns = [
            r'(\w+)\s*[::]\s*(\d+(?:\.\d+)?)',
            r'(\d+(?:\.\d+)?)\s*[::]\s*(\w+)',
        ]
        
        data = {}
        for pattern in patterns:
            matches = re.findall(pattern, text)
            for match in matches:
                if len(match) == 2:
                    key, value = match
                    try:
                        data[key] = float(value)
                    except ValueError:
                        pass
        
        return data
    
    def save_to_png(self, output_path, dpi=150):
        """Save chart as PNG"""
        if self.fig:
            self.fig.savefig(output_path, dpi=dpi, bbox_inches='tight', 
                           facecolor='white', edgecolor='none')
            return output_path
    
    def save_to_svg(self, output_path):
        """Save chart as SVG"""
        if self.fig:
            self.fig.savefig(output_path, format='svg', bbox_inches='tight',
                           facecolor='white', edgecolor='none')
            return output_path
    
    def save_to_pdf(self, output_path):
        """Save chart as PDF"""
        if self.fig:
            self.fig.savefig(output_path, format='pdf', bbox_inches='tight',
                           facecolor='white', edgecolor='none')
            return output_path
    
    def save_to_base64(self, format='png'):
        """Convert chart to base64 string for embedding"""
        import io
        import base64
        
        if self.fig:
            buffer = io.BytesIO()
            self.fig.savefig(buffer, format=format, bbox_inches='tight',
                           facecolor='white', edgecolor='none')
            buffer.seek(0)
            img_str = base64.b64encode(buffer.read()).decode()
            return f'data:image/{format};base64,{img_str}'
    
    def embed_in_markdown(self, title='', caption=''):
        """Generate markdown with embedded chart"""
        base64_img = self.save_to_base64('png')
        
        md = f'\n'
        if title:
            md += f'## {title}\n\n'
        md += f'![{title}]({base64_img})\n'
        if caption:
            md += f'\n*{caption}*\n'
        
        return md
    
    def embed_in_html(self, title='', width='100%'):
        """Generate HTML with embedded chart"""
        base64_img = self.save_to_base64('png')
        
        html = f'''

    {f'{title}' if title else ''}
    

'''
        return html
    
    def save_to_word(self, output_path, title='', caption=''):
        """Save chart to Word document"""
        from docx import Document
        from docx.shared import Inches
        
        doc = Document()
        
        if title:
            doc.add_heading(title, level=2)
        
        # Save chart as temporary image
        temp_img = output_path.replace('.docx', '_temp.png')
        self.save_to_png(temp_img)
        
        # Add image to document
        doc.add_picture(temp_img, width=Inches(6))
        
        if caption:
            last_para = doc.paragraphs[-1]
            last_para.alignment = 1  # Center
        
        doc.save(output_path)
        
        # Clean up temp file
        if os.path.exists(temp_img):
            os.remove(temp_img)
        
        return output_path

# Example usage
generator = ChartGenerator()
output_dir = os.environ.get('OPENCLAW_WORKSPACE', os.getcwd())

# Bar chart
labels = ['Q1', 'Q2', 'Q3', 'Q4']
values = [150000, 180000, 220000, 280000]
generator.create_bar_chart(
    labels, values,
    title='2026 Quarterly Sales',
    xlabel='Quarter',
    ylabel='Sales ($)',
    output_path=os.path.join(output_dir, 'bar_chart.png')
)

# Line chart
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
product_a = [100, 120, 140, 160, 180, 200]
product_b = [80, 95, 110, 130, 150, 170]
generator.create_line_chart(
    months, [product_a, product_b],
    labels=['Product A', 'Product B'],
    title='Sales Trend',
    xlabel='Month',
    ylabel='Sales',
    output_path=os.path.join(output_dir, 'line_chart.png')
)

# Pie chart
pie_labels = ['Product A', 'Product B', 'Product C', 'Others']
pie_values = [35, 25, 20, 20]
generator.create_pie_chart(
    pie_labels, pie_values,
    title='Market Share',
    output_path=os.path.join(output_dir, 'pie_chart.png')
)

print(f"✅ Charts generated in: {output_dir}")
PYEOF

Data Sources (数据来源)

From CSV

generator = ChartGenerator()
data = generator.load_from_csv('data.csv', x_col='Month', y_cols=['Sales', 'Profit'])

generator.create_line_chart(
    data['x'], 
    [data['y']['Sales'], data['y']['Profit']],
    labels=['Sales', 'Profit'],
    title='Monthly Performance'
)

From Excel

data = generator.load_from_excel('report.xlsx', sheet_name='Sheet1')

Manual Input

labels = ['A', 'B', 'C', 'D']
values = [100, 200, 150, 300]
generator.create_bar_chart(labels, values)

Styling Options (样式选项)

Colors

# Single color
color='#3182ce'  # Blue

# Multiple colors
colors=['#3182ce', '#48bb78', '#ed8936', '#e53e3e']

Size

# Default size
figsize=(10, 6)

# Large for presentations
figsize=(16, 9)

# Square for reports
figsize=(8, 8)

Security Notes

  • ✅ No network calls or external endpoints
  • ✅ No credentials or API keys required
  • ✅ Local file processing only
  • ✅ Open source dependencies (matplotlib, pandas)
  • ✅ No data uploaded to external servers

Notes

  • Uses matplotlib for chart generation
  • Supports CSV, Excel, and manual data input
  • Output formats: PNG, SVG, PDF
  • Chinese font support with Noto Sans SC
  • Cross-platform compatible

相关技能

把自然语言描述转为结构化 JSON,并由 mcp-diagram-generator MCP 服务生成 Draw.io、Mermaid 或 Excalidraw 图表文件。

作者 nssa.io1.0k 次安装47 星标

诊断生产力系统反复失效的根因,给出最小干预——容量测算、瓶颈定位、可靠的本地记录。

作者 Iván855 次安装69 星标

从 AdMapix API 拉取广告创意、应用、榜单和收入预估等数据,原样返回结构化 JSON。

作者 fly0pants4.3k 次安装296 星标

在本地磁盘以分类纯 Markdown 文件保存需要长期留存的事实,与智能体内置记忆并存。

作者 Iván559 次安装18 星标

以 AI 机器人身份加入视频会议,提供语音、虚拟形象与屏幕共享四种模式。

作者 johnpatternai22 次安装8 星标

tobewin 的更多技能

浏览全部技能

用一份 JSON 描述就能生成标准可编辑的 PPTX,自带 11 种版式与 5 套配色。

作者 ToBeWin329 次安装3 星标

把 Word、PDF、Excel、PowerPoint、HTML、Markdown 与 TXT 文档翻译成另一种语言,同时保留原始排版。

作者 tobewin36 次安装1 星标

Professional Excel spreadsheet generator. Use when user needs to create data tables, reports, charts, financial models, or any structured data in Excel forma...

作者 ToBeWin82 次安装3 星标

中国新闻资讯聚合工具。Use when user wants to get latest news from Chinese sources. Supports multiple news sites (Sina, Sohu, NetEase, Tencent) via browser automation an...

作者 ToBeWin57 次安装3 星标

Data analysis tool for Excel, CSV, Word, PDF, TXT, Markdown files. Use when user needs to analyze, summarize, or compare data from multiple files. Supports f...

作者 ToBeWin68 次安装1 星标

Marketing plan generator with web research and Word output. Use when user needs to create marketing plans, promotional campaigns, social media strategies. Fe...

作者 ToBeWin31 次安装1 星标