|
1 | 1 | """ |
2 | 2 | area-basic: Basic Area Chart |
3 | | -Implementation for: plotly |
4 | | -Variant: default |
5 | | -Python: 3.10+ |
| 3 | +Library: plotly |
6 | 4 | """ |
7 | 5 |
|
8 | | -from typing import TYPE_CHECKING, Optional |
9 | | - |
10 | 6 | import pandas as pd |
11 | 7 | import plotly.graph_objects as go |
12 | 8 |
|
13 | 9 |
|
14 | | -if TYPE_CHECKING: |
15 | | - pass |
16 | | - |
17 | | - |
18 | | -def create_plot( |
19 | | - data: pd.DataFrame, |
20 | | - x: str, |
21 | | - y: str, |
22 | | - title: Optional[str] = None, |
23 | | - xlabel: Optional[str] = None, |
24 | | - ylabel: Optional[str] = None, |
25 | | - color: str = "rgba(99, 110, 250, 0.5)", |
26 | | - line_color: Optional[str] = None, |
27 | | - line_width: float = 2.0, |
28 | | - fill_to: str = "tozeroy", |
29 | | - height: int = 900, |
30 | | - width: int = 1600, |
31 | | - **kwargs, |
32 | | -) -> go.Figure: |
33 | | - """ |
34 | | - Create a basic area chart showing quantitative data over a continuous interval. |
35 | | -
|
36 | | - The area between the line and the x-axis is filled with color, emphasizing |
37 | | - the magnitude of values. Ideal for showing trends and cumulative totals. |
38 | | -
|
39 | | - Args: |
40 | | - data: Input DataFrame with required columns |
41 | | - x: Column name for x-axis values (typically time or sequential data) |
42 | | - y: Column name for y-axis values (numeric) |
43 | | - title: Plot 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 | | - color: Fill color for the area with alpha (default: semi-transparent blue) |
47 | | - line_color: Color of the line at top of area (default: derived from fill color) |
48 | | - line_width: Width of the line (default: 2.0) |
49 | | - fill_to: Fill mode - 'tozeroy', 'tonexty', 'none' (default: 'tozeroy') |
50 | | - height: Figure height in pixels (default: 900) |
51 | | - width: Figure width in pixels (default: 1600) |
52 | | - **kwargs: Additional parameters passed to plotly Scatter trace |
53 | | -
|
54 | | - Returns: |
55 | | - Plotly Figure object |
56 | | -
|
57 | | - Raises: |
58 | | - ValueError: If data is empty |
59 | | - KeyError: If required columns not found |
60 | | -
|
61 | | - Example: |
62 | | - >>> data = pd.DataFrame({ |
63 | | - ... 'Month': ['Jan', 'Feb', 'Mar', 'Apr', 'May'], |
64 | | - ... 'Sales': [100, 150, 130, 180, 200] |
65 | | - ... }) |
66 | | - >>> fig = create_plot(data, x='Month', y='Sales', title='Monthly Sales') |
67 | | - """ |
68 | | - # Input validation |
69 | | - if data.empty: |
70 | | - raise ValueError("Data cannot be empty") |
71 | | - |
72 | | - # Check required columns |
73 | | - for col in [x, y]: |
74 | | - if col not in data.columns: |
75 | | - available = ", ".join(data.columns) |
76 | | - raise KeyError(f"Column '{col}' not found. Available columns: {available}") |
77 | | - |
78 | | - # Derive line color from fill color if not provided |
79 | | - if line_color is None: |
80 | | - # Use a solid version of the fill color (darker) |
81 | | - line_color = "rgb(99, 110, 250)" |
82 | | - |
83 | | - # Create the figure |
84 | | - fig = go.Figure() |
85 | | - |
86 | | - # Add the area trace |
87 | | - fig.add_trace( |
88 | | - go.Scatter( |
89 | | - x=data[x], |
90 | | - y=data[y], |
91 | | - mode="lines", |
92 | | - fill=fill_to, |
93 | | - fillcolor=color, |
94 | | - line={"color": line_color, "width": line_width}, |
95 | | - name=y, |
96 | | - hovertemplate=f"<b>{x}</b>: %{{x}}<br><b>{y}</b>: %{{y:,.2f}}<extra></extra>", |
97 | | - **kwargs, |
98 | | - ) |
| 10 | +# Data |
| 11 | +data = pd.DataFrame( |
| 12 | + { |
| 13 | + "month": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], |
| 14 | + "sales": [120, 135, 148, 162, 175, 195, 210, 198, 185, 170, 158, 190], |
| 15 | + } |
| 16 | +) |
| 17 | + |
| 18 | +# Create figure |
| 19 | +fig = go.Figure() |
| 20 | + |
| 21 | +fig.add_trace( |
| 22 | + go.Scatter( |
| 23 | + x=data["month"], |
| 24 | + y=data["sales"], |
| 25 | + mode="lines", |
| 26 | + fill="tozeroy", |
| 27 | + fillcolor="rgba(48, 105, 152, 0.4)", |
| 28 | + line={"color": "#306998", "width": 2}, |
| 29 | + name="Sales", |
99 | 30 | ) |
100 | | - |
101 | | - # Update layout for professional appearance |
102 | | - fig.update_layout( |
103 | | - title={ |
104 | | - "text": title or "Area Chart", |
105 | | - "font": {"size": 18, "family": "Arial, sans-serif"}, |
106 | | - "x": 0.5, |
107 | | - "xanchor": "center", |
108 | | - }, |
109 | | - xaxis={ |
110 | | - "title": {"text": xlabel or x, "font": {"size": 14}}, |
111 | | - "showgrid": True, |
112 | | - "gridcolor": "rgba(128, 128, 128, 0.3)", |
113 | | - "gridwidth": 1, |
114 | | - "zeroline": False, |
115 | | - "showline": True, |
116 | | - "linewidth": 1, |
117 | | - "linecolor": "rgba(128, 128, 128, 0.5)", |
118 | | - }, |
119 | | - yaxis={ |
120 | | - "title": {"text": ylabel or y, "font": {"size": 14}}, |
121 | | - "showgrid": True, |
122 | | - "gridcolor": "rgba(128, 128, 128, 0.3)", |
123 | | - "gridwidth": 1, |
124 | | - "zeroline": True, |
125 | | - "zerolinewidth": 1, |
126 | | - "zerolinecolor": "rgba(128, 128, 128, 0.5)", |
127 | | - "showline": True, |
128 | | - "linewidth": 1, |
129 | | - "linecolor": "rgba(128, 128, 128, 0.5)", |
130 | | - }, |
131 | | - plot_bgcolor="white", |
132 | | - paper_bgcolor="white", |
133 | | - height=height, |
134 | | - width=width, |
135 | | - showlegend=False, |
136 | | - hovermode="x unified", |
137 | | - hoverlabel={"bgcolor": "white", "font_size": 12, "font_family": "Arial, sans-serif"}, |
138 | | - margin={"l": 80, "r": 40, "t": 80, "b": 60}, |
139 | | - ) |
140 | | - |
141 | | - return fig |
142 | | - |
143 | | - |
144 | | -if __name__ == "__main__": |
145 | | - import numpy as np |
146 | | - |
147 | | - # Sample data: Monthly website traffic over a year |
148 | | - np.random.seed(42) |
149 | | - |
150 | | - months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] |
151 | | - |
152 | | - # Generate realistic traffic pattern with seasonal variation |
153 | | - base_traffic = 10000 |
154 | | - seasonal_factor = [0.8, 0.85, 0.95, 1.0, 1.1, 1.15, 1.2, 1.25, 1.1, 1.0, 0.9, 0.95] |
155 | | - noise = np.random.normal(0, 500, 12) |
156 | | - |
157 | | - traffic = [int(base_traffic * sf + n) for sf, n in zip(seasonal_factor, noise, strict=False)] |
158 | | - |
159 | | - data = pd.DataFrame({"Month": months, "Visitors": traffic}) |
160 | | - |
161 | | - # Create the area chart |
162 | | - fig = create_plot( |
163 | | - data, |
164 | | - x="Month", |
165 | | - y="Visitors", |
166 | | - title="Monthly Website Visitors (2024)", |
167 | | - xlabel="Month", |
168 | | - ylabel="Number of Visitors", |
169 | | - color="rgba(99, 110, 250, 0.4)", |
170 | | - line_color="rgb(99, 110, 250)", |
171 | | - line_width=2.5, |
172 | | - ) |
173 | | - |
174 | | - # Save as PNG |
175 | | - fig.write_image("plot.png", width=1600, height=900, scale=2) |
176 | | - print("Plot saved to plot.png") |
| 31 | +) |
| 32 | + |
| 33 | +# Layout |
| 34 | +fig.update_layout( |
| 35 | + title={"text": "Monthly Sales", "font": {"size": 20}, "x": 0.5, "xanchor": "center"}, |
| 36 | + xaxis_title={"text": "Month", "font": {"size": 20}}, |
| 37 | + yaxis_title={"text": "Sales", "font": {"size": 20}}, |
| 38 | + template="plotly_white", |
| 39 | + xaxis={"tickfont": {"size": 16}, "showgrid": True, "gridcolor": "rgba(0,0,0,0.1)"}, |
| 40 | + yaxis={"tickfont": {"size": 16}, "showgrid": True, "gridcolor": "rgba(0,0,0,0.1)"}, |
| 41 | + showlegend=False, |
| 42 | + margin={"l": 80, "r": 40, "t": 80, "b": 80}, |
| 43 | +) |
| 44 | + |
| 45 | +# Save |
| 46 | +fig.write_image("plot.png", width=1600, height=900, scale=3) |
0 commit comments