|
| 1 | +""" |
| 2 | +area-basic: Basic Area Chart |
| 3 | +Implementation for: pygal |
| 4 | +Variant: default |
| 5 | +Python: 3.10+ |
| 6 | +""" |
| 7 | + |
| 8 | +from typing import TYPE_CHECKING, Optional |
| 9 | + |
| 10 | +import pandas as pd |
| 11 | +import pygal |
| 12 | +from pygal.style import Style |
| 13 | + |
| 14 | + |
| 15 | +if TYPE_CHECKING: |
| 16 | + from pygal import Line |
| 17 | + |
| 18 | + |
| 19 | +def create_plot( |
| 20 | + data: pd.DataFrame, |
| 21 | + x: str, |
| 22 | + y: str, |
| 23 | + title: Optional[str] = None, |
| 24 | + xlabel: Optional[str] = None, |
| 25 | + ylabel: Optional[str] = None, |
| 26 | + fill_alpha: float = 0.5, |
| 27 | + color: Optional[str] = None, |
| 28 | + show_line: bool = True, |
| 29 | + width: int = 1600, |
| 30 | + height: int = 900, |
| 31 | + **kwargs, |
| 32 | +) -> "Line": |
| 33 | + """ |
| 34 | + Create a basic area chart showing a filled area under a line using pygal. |
| 35 | +
|
| 36 | + An area chart displays a single data series as a filled region beneath |
| 37 | + a line, ideal for showing trends while emphasizing magnitude. |
| 38 | +
|
| 39 | + Args: |
| 40 | + data: Input DataFrame with required columns |
| 41 | + x: Column name for x-axis values (categories/labels) |
| 42 | + y: Column name for y-axis numeric values |
| 43 | + title: Chart title (optional) |
| 44 | + xlabel: Custom x-axis label (optional, defaults to column name) |
| 45 | + ylabel: Custom y-axis label (optional, defaults to column name) |
| 46 | + fill_alpha: Transparency of the filled area (default: 0.5) |
| 47 | + color: Color for the line and fill (optional) |
| 48 | + show_line: Whether to show the line on top of fill (default: True) |
| 49 | + width: Figure width in pixels (default: 1600) |
| 50 | + height: Figure height in pixels (default: 900) |
| 51 | + **kwargs: Additional parameters for pygal configuration |
| 52 | +
|
| 53 | + Returns: |
| 54 | + pygal Line chart object configured as an area chart |
| 55 | +
|
| 56 | + Raises: |
| 57 | + ValueError: If data is empty |
| 58 | + KeyError: If required columns not found |
| 59 | +
|
| 60 | + Example: |
| 61 | + >>> data = pd.DataFrame({ |
| 62 | + ... 'Month': ['Jan', 'Feb', 'Mar', 'Apr', 'May'], |
| 63 | + ... 'Sales': [100, 150, 130, 180, 200] |
| 64 | + ... }) |
| 65 | + >>> chart = create_plot(data, x='Month', y='Sales') |
| 66 | + """ |
| 67 | + # Input validation |
| 68 | + if data.empty: |
| 69 | + raise ValueError("Data cannot be empty") |
| 70 | + |
| 71 | + # Check required columns |
| 72 | + for col in [x, y]: |
| 73 | + if col not in data.columns: |
| 74 | + available = ", ".join(data.columns) |
| 75 | + raise KeyError(f"Column '{col}' not found. Available columns: {available}") |
| 76 | + |
| 77 | + # Define colors - use provided color or default |
| 78 | + primary_color = color or "#3498db" |
| 79 | + |
| 80 | + # Create custom style with appropriate opacity for fill |
| 81 | + custom_style = Style( |
| 82 | + background="white", |
| 83 | + plot_background="white", |
| 84 | + foreground="#333", |
| 85 | + foreground_strong="#333", |
| 86 | + foreground_subtle="#555", |
| 87 | + opacity=fill_alpha, |
| 88 | + opacity_hover=min(fill_alpha + 0.2, 1.0), |
| 89 | + colors=(primary_color,), |
| 90 | + font_family="Arial, sans-serif", |
| 91 | + major_guide_stroke_dasharray="3,3", |
| 92 | + guide_stroke_dasharray="1,1", |
| 93 | + ) |
| 94 | + |
| 95 | + # Create line chart with fill enabled (makes it an area chart) |
| 96 | + chart = pygal.Line( |
| 97 | + title=title or "Area Chart", |
| 98 | + x_title=xlabel or x, |
| 99 | + y_title=ylabel or y, |
| 100 | + width=width, |
| 101 | + height=height, |
| 102 | + fill=True, # This enables the area fill |
| 103 | + show_legend=True, |
| 104 | + style=custom_style, |
| 105 | + show_x_guides=True, |
| 106 | + show_y_guides=True, |
| 107 | + dots_size=3 if show_line else 0, |
| 108 | + stroke_style={"width": 2} if show_line else {"width": 0}, |
| 109 | + **kwargs, |
| 110 | + ) |
| 111 | + |
| 112 | + # Set x-axis labels |
| 113 | + x_values = data[x].tolist() |
| 114 | + chart.x_labels = [str(val) for val in x_values] |
| 115 | + |
| 116 | + # Add the data series |
| 117 | + y_values = data[y].tolist() |
| 118 | + series_label = ylabel or y |
| 119 | + chart.add(series_label, y_values) |
| 120 | + |
| 121 | + return chart |
| 122 | + |
| 123 | + |
| 124 | +if __name__ == "__main__": |
| 125 | + # Sample data for testing - monthly website traffic |
| 126 | + data = pd.DataFrame( |
| 127 | + { |
| 128 | + "Month": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], |
| 129 | + "Visitors": [12000, 15000, 18000, 22000, 25000, 28000, 30000, 32000, 29000, 26000, 23000, 20000], |
| 130 | + } |
| 131 | + ) |
| 132 | + |
| 133 | + # Create plot |
| 134 | + chart = create_plot( |
| 135 | + data, |
| 136 | + x="Month", |
| 137 | + y="Visitors", |
| 138 | + title="Monthly Website Traffic", |
| 139 | + xlabel="Month", |
| 140 | + ylabel="Number of Visitors", |
| 141 | + fill_alpha=0.5, |
| 142 | + color="#2ecc71", |
| 143 | + ) |
| 144 | + |
| 145 | + # Save as PNG |
| 146 | + chart.render_to_png("plot.png") |
| 147 | + print("Plot saved to plot.png") |
0 commit comments