# Layouts, Styling, and Customization ## Subplots ### Creating Subplots ```python from plotly.subplots import make_subplots import plotly.graph_objects as go # Basic grid fig = make_subplots(rows=2, cols=2) # Add traces to specific positions fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6]), row=1, col=1) fig.add_trace(go.Bar(x=['A', 'B', 'C'], y=[1, 3, 2]), row=1, col=2) fig.add_trace(go.Scatter(x=[1, 2, 3], y=[2, 3, 4]), row=2, col=1) ``` ### Subplot Options ```python fig = make_subplots( rows=2, cols=2, # Titles subplot_titles=('Plot 1', 'Plot 2', 'Plot 3', 'Plot 4'), # Custom dimensions column_widths=[0.7, 0.3], row_heights=[0.4, 0.6], # Spacing horizontal_spacing=0.1, vertical_spacing=0.15, # Shared axes shared_xaxes=True, # or 'columns', 'rows', 'all' shared_yaxes=False, # Trace types (optional, for mixed types) specs=[[{'type': 'scatter'}, {'type': 'bar'}], [{'type': 'surface'}, {'type': 'table'}]] ) ``` ### Mixed Subplot Types ```python from plotly.subplots import make_subplots import plotly.graph_objects as go # 2D and 3D subplots fig = make_subplots( rows=1, cols=2, specs=[[{'type': 'scatter'}, {'type': 'scatter3d'}]] ) fig.add_trace(go.Scatter(x=[1, 2], y=[3, 4]), row=1, col=1) fig.add_trace(go.Scatter3d(x=[1, 2], y=[3, 4], z=[5, 6]), row=1, col=2) ``` ### Customizing Subplot Axes ```python # Update specific subplot axes fig.update_xaxes(title_text='X Label', row=1, col=1) fig.update_yaxes(title_text='Y Label', range=[0, 100], row=2, col=1) # Update all x-axes fig.update_xaxes(showgrid=True, gridcolor='lightgray') ``` ### Shared Colorscale ```python fig = make_subplots(rows=1, cols=2) fig.add_trace(go.Bar(x=['A', 'B'], y=[1, 2], marker=dict(color=[1, 2], coloraxis='coloraxis')), row=1, col=1) fig.add_trace(go.Bar(x=['C', 'D'], y=[3, 4], marker=dict(color=[3, 4], coloraxis='coloraxis')), row=1, col=2) fig.update_layout(coloraxis=dict(colorscale='Viridis')) ``` ## Templates and Themes ### Built-in Templates ```python import plotly.express as px import plotly.io as pio # Available templates templates = [ 'plotly', # Default 'plotly_white', # White background 'plotly_dark', # Dark theme 'ggplot2', # ggplot2 style 'seaborn', # Seaborn style 'simple_white', # Minimal white 'presentation', # For presentations 'xgridoff', # No x grid 'ygridoff', # No y grid 'gridon', # Grid on 'none' # No styling ] # Use in Plotly Express fig = px.scatter(df, x='x', y='y', template='plotly_dark') # Use in graph_objects fig.update_layout(template='seaborn') # Set default template for session pio.templates.default = 'plotly_white' ``` ### Custom Templates ```python import plotly.graph_objects as go import plotly.io as pio # Create custom template custom_template = go.layout.Template( layout=go.Layout( font=dict(family='Arial', size=14), plot_bgcolor='#f0f0f0', paper_bgcolor='white', colorway=['#1f77b4', '#ff7f0e', '#2ca02c'], title_font_size=20 ) ) # Register template pio.templates['custom'] = custom_template # Use it fig = px.scatter(df, x='x', y='y', template='custom') ``` ## Styling with Plotly Express ### Built-in Arguments ```python fig = px.scatter( df, x='x', y='y', # Dimensions width=800, height=600, # Title title='Figure Title', # Labels labels={'x': 'X Axis Label', 'y': 'Y Axis Label'}, # Colors color='category', color_discrete_sequence=px.colors.qualitative.Set2, color_discrete_map={'A': 'red', 'B': 'blue'}, color_continuous_scale='Viridis', # Ordering category_orders={'category': ['A', 'B', 'C']}, # Template template='plotly_white' ) ``` ### Setting Defaults ```python import plotly.express as px # Session-wide defaults px.defaults.template = 'plotly_white' px.defaults.width = 800 px.defaults.height = 600 px.defaults.color_continuous_scale = 'Viridis' ``` ## Color Scales ### Discrete Colors ```python import plotly.express as px # Named color sequences color_sequences = [ px.colors.qualitative.Plotly, px.colors.qualitative.D3, px.colors.qualitative.G10, px.colors.qualitative.Set1, px.colors.qualitative.Pastel, px.colors.qualitative.Dark2, ] fig = px.scatter(df, x='x', y='y', color='category', color_discrete_sequence=px.colors.qualitative.Set2) ``` ### Continuous Colors ```python # Named continuous scales continuous_scales = [ 'Viridis', 'Plasma', 'Inferno', 'Magma', 'Cividis', # Perceptually uniform 'Blues', 'Greens', 'Reds', 'YlOrRd', 'YlGnBu', # Sequential 'RdBu', 'RdYlGn', 'Spectral', 'Picnic', # Diverging ] fig = px.scatter(df, x='x', y='y', color='value', color_continuous_scale='Viridis') # Reverse scale fig = px.scatter(df, x='x', y='y', color='value', color_continuous_scale='Viridis_r') # Custom scale fig = px.scatter(df, x='x', y='y', color='value', color_continuous_scale=['blue', 'white', 'red']) ``` ### Colorbar Customization ```python fig.update_coloraxes( colorbar=dict( title='Value', tickmode='linear', tick0=0, dtick=10, len=0.7, # Length relative to plot thickness=20, x=1.02 # Position ) ) ``` ## Layout Customization ### Title and Fonts ```python fig.update_layout( title=dict( text='Main Title', font=dict(size=24, family='Arial', color='darkblue'), x=0.5, # Center title xanchor='center' ), font=dict( family='Arial', size=14, color='black' ) ) ``` ### Margins and Size ```python fig.update_layout( width=1000, height=600, margin=dict( l=50, # left r=50, # right t=100, # top b=50, # bottom pad=10 # padding ), autosize=True # Auto-resize to container ) ``` ### Background Colors ```python fig.update_layout( plot_bgcolor='#f0f0f0', # Plot area paper_bgcolor='white' # Figure background ) ``` ### Legend ```python fig.update_layout( showlegend=True, legend=dict( title='Legend Title', orientation='h', # 'h' or 'v' x=0.5, # Position y=-0.2, xanchor='center', yanchor='top', bgcolor='rgba(255, 255, 255, 0.8)', bordercolor='black', borderwidth=1, font=dict(size=12) ) ) ``` ### Axes ```python fig.update_xaxes( title='X Axis Title', title_font=dict(size=16, family='Arial'), # Range range=[0, 10], autorange=True, # Auto range # Grid showgrid=True, gridwidth=1, gridcolor='lightgray', # Ticks showticklabels=True, tickmode='linear', tick0=0, dtick=1, tickformat='.2f', tickangle=-45, # Zero line zeroline=True, zerolinewidth=2, zerolinecolor='black', # Scale type='linear', # 'linear', 'log', 'date', 'category' ) fig.update_yaxes( title='Y Axis Title', # ... same options as xaxes ) ``` ### Hover Behavior ```python fig.update_layout( hovermode='closest', # 'x', 'y', 'closest', 'x unified', False ) # Customize hover template fig.update_traces( hovertemplate='%{x}
Value: %{y:.2f}' ) ``` ### Annotations ```python fig.add_annotation( text='Important Note', x=2, y=5, showarrow=True, arrowhead=2, arrowsize=1, arrowwidth=2, arrowcolor='red', ax=40, # Arrow x offset ay=-40, # Arrow y offset font=dict(size=14, color='black'), bgcolor='yellow', opacity=0.8 ) ``` ### Shapes ```python # Rectangle fig.add_shape( type='rect', x0=1, y0=2, x1=3, y1=4, line=dict(color='red', width=2), fillcolor='lightblue', opacity=0.3 ) # Circle fig.add_shape( type='circle', x0=0, y0=0, x1=1, y1=1, line_color='purple' ) # Convenience methods fig.add_hline(y=5, line_dash='dash', line_color='red', annotation_text='Threshold') fig.add_vline(x=3, line_dash='dot') fig.add_vrect(x0=1, x1=2, fillcolor='green', opacity=0.2) fig.add_hrect(y0=4, y1=6, fillcolor='red', opacity=0.2) ``` ## Update Methods ### Update Layout ```python fig.update_layout( title='New Title', xaxis_title='X', yaxis_title='Y' ) ``` ### Update Traces ```python # Update all traces fig.update_traces(marker=dict(size=10, opacity=0.7)) # Update with selector fig.update_traces( marker=dict(color='red'), selector=dict(mode='markers', name='Series 1') ) ``` ### Update Axes ```python fig.update_xaxes(showgrid=True, gridcolor='lightgray') fig.update_yaxes(type='log') ``` ## Responsive Design ```python # Auto-resize to container fig.update_layout(autosize=True) # Responsive in HTML fig.write_html('plot.html', config={'responsive': True}) ```