Public account: You and the cabin by: Peter Editor: Peter

Visualization artifact Plotly play multiple subgraph drawing

Hello, I’m Peter

It has been a long time since Plotly plotted. In the past, we have introduced how to draw bar charts, pie charts, violin charts, Sankey charts, etc. Today, we will introduce how Plotly plotted multiple subgraphs, and how to draw multiple types of graphs in a single canvas.

Serialized article by Plotly

Multisubgraph drawing

First look at the actual results:

There are two ways to draw subgraphs in Plotly, based on plotly_Express and Graph_Objects.

But plotly_Express only supports facet_plots and marginal distribution subplots, Only the graph_objects module that is based on the make_subplots will draw true subplots. Here are some practical examples.

import pandas as pd
import numpy as np

import plotly_express as px
import plotly.graph_objects as go

# Draw a subgraph
from plotly.subplots import make_subplots
Copy the code

It is important to import the make_subplots module.

Based on the plotly_express

Plotly_express draws’ subgraphs ‘by using the parameters marginal_x and marginal_y, which represent the type of graphs at the margin. This can be’ histogram ‘, ‘rug’, ‘box’, or ‘violin’.

Based on the facet_plots

A section graph is a graph made up of multiple plots with the same coaxial set, each of which shows a subset of the data, also known as trellis (grid) plots or small multiples. It is more appropriate to directly publish in official English, but I cannot find a proper Chinese translation for the time being.

Different graphics section display

To import the built-in consumption data set:

1. Section graph based on scatter graph

fig = px.scatter(tips,  # data
                 x="total_bill".# xy
                 y="tip", 
                 color="smoker".# color
                 facet_col="day"  # column direction section field
                )
fig.show()
Copy the code

2. Section display based on bar chart

# 2. Section of bar chart

fig = px.bar(tips, 
             x="size", 
             y="total_bill", 
             color="day", 
             facet_row="smoker"  # Line direction section field: Smoking or not
            )
fig.show()
Copy the code

Control the number of subgraphs

3. Wrapping column Facets: Control the section figure showing the number of elements

The facet_col_wrap parameter can be used to control the maximum number of graphics to be displayed on each row. The wrap parameter can be used to limit the number of graphics to be displayed on each row.

Using the built-in GDP data set:

# 3. Section diagram with limited number of graphs per line

fig = px.scatter(gdp,   # data set
                 x='gdpPercap'.# x, y, color, dot size
                 y='lifeExp', 
                 color='continent', 
                 size='pop',
                 facet_col='continent'.# column section field
                 facet_col_wrap=3 # Maximum 3 shapes per line
                )
fig.show()
Copy the code

The COL field of the section figure above is continents, and there are only 5 continents at most. The figure below uses the time year:

fig = px.scatter(gdp,   # data set
                 x='gdpPercap'.# x, y, color, dot size
                 y='lifeExp', 
                 color='continent', 
                 size='pop',
                 facet_col='year'.# column section field
                 facet_col_wrap=3  # Maximum 3 shapes per line
                )
fig.show()
Copy the code

Each line displays a maximum of 4 figures:

fig = px.scatter(gdp, 
                 x='gdpPercap', 
                 y='lifeExp', 
                 color='continent', 
                 size='pop',
                 facet_col='year', 
                 facet_col_wrap=4  # Maximum 4 shapes per line
                )
fig.show()
Copy the code

Subgraph axis Settings

By default, the Y-axis of the subgraph is the same:

The default is the same for the y axis
By default, the Y-axis ranges are the same
fig = px.scatter(tips, 
                 x="total_bill", 
                 y="tip", 
                 color='day', 
                 facet_row="time"
                )
fig.show()
Copy the code

Do not share the Y-axis by setting the following parameters:

fig = px.scatter(tips, 
                 x="total_bill", 
                 y="tip", 
                 color='day', 
                 facet_row="time"  # Column direction upper section diagram
                )

# 设置不共享y轴,对应的是facet_row
fig.update_yaxes(matches=None)

fig.show()
Copy the code

If it is a slice of facet_col in the column direction, you can set not to share the X-axis

fig = px.scatter(tips, 
                 x="total_bill", 
                 y="tip", 
                 color='day', 
                 facet_col="time"  # Column direction upper section diagram
                )

# 设置不共享x轴,对应的是facet_col
fig.update_xaxes(matches=None)

fig.show()
Copy the code

Subgraph title Settings

fig = px.scatter(tips,
                 x="total_bill", 
                 y="tip", 
                 color="time",
                 facet_col="smoker"
                )
fig.show()
Copy the code

Change the title of the subgraph by setting:

fig = px.scatter(tips, 
                 x="total_bill", 
                 y="tip", 
                 color="time",
                 facet_col="smoker"
                )

# Add code: Cut each line header by = and extract the last element
fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]))  

fig.show()
Copy the code

Based on Marginal figure

This method is mainly implemented via marginal_x and marginal_y. First import the dataset:

Based on the marginal graph of different graphs

1. Based on scatter diagram:

fig = px.scatter(iris,  # data set
                 x="sepal_length".# specify the xy axis
                 y="sepal_width",
                 marginal_x="rug".# Marginal graph type: histogram
                 marginal_y="histogram"  # shaft must figure
                )

fig.show()
Copy the code

2. Marginal graph setting based on density heat map:

fig = px.density_heatmap(
    iris,  # data
    x="sepal_width".# two axes
    y="sepal_length",  
    marginal_x="violin".# Marginal diagram: Violin and box diagram
    marginal_y="box")

fig.show()
Copy the code

3. Marginal map color setting

fig = px.scatter(iris,
                 x="sepal_length", 
                 y="sepal_width", 
                 color="species".# Color Settings also apply to marginal graphs
                 marginal_x="violin", 
                 marginal_y="box",
                 title="Marginal map color Settings")
fig.show()
Copy the code

The marginal map and section map are used together

fig = px.scatter(
    tips, 
    x="total_bill",
    y="tip", 
    color="sex", 
    facet_col="day".# date field slice
    marginal_x="violin"  # Fiddle-map marginal map
)

fig.show()
Copy the code

Based on the graph_objects

The graph_objects method is actually implemented using the make_subplots function. Be sure to enter first:

This way you must import modules

from plotly.subplots import make_subplots
import plotly.graph_objects as go
Copy the code

Based on subgraph

Two basic parameters: set row and column
fig = make_subplots(rows=1, cols=2)  # 1 row, 2 columns

# Add two data tracks to form two graphs
fig.add_trace(
    go.Scatter(x=[1.2.3], y=[5.10.15]),
    row=1, col=1  # first row, first column
)

fig.add_trace(
    go.Scatter(x=[20.30.40], y=[60.70.80]),
    row=1, col=2  # first row, second column
)

# Set the width, height and title of the graphic
fig.update_layout(height=600, 
                  width=800, 
                  title_text="Subgraph making")
fig.show()
Copy the code

fig = make_subplots(rows=3, cols=1)  # 3 row 1 column

Add 3 data tracks
fig.add_trace(
    go.Scatter(x=[1.2.3], y=[5.10.15]),
    row=1, col=1  # 1 * 1
)

fig.add_trace(
    go.Scatter(x=[20.30.40], y=[60.70.80]),
    row=2, col=1  2 * # 1
)

fig.add_trace(
    go.Scatter(x=[50.60.70], y=[110.120.130]),
    row=3, col=1  # 3 * 1
)

fig.update_layout(height=600, 
                  width=800, 
                  title_text="Subgraph making")
fig.show()
Copy the code

Multi-row, multi-column subgraph

With multiple rows and columns, we can specify the position of the first graph, indicating where the graph starts. The default upper left corner is the location of the first graph.

\fig = make_subplots(rows=2, cols=2.# 2 rows, 2 columns
                    start_cell="bottom-left"# Position of the first graph, two options: bottom-left', 'top-left '
                   )  

Add 4 data tracks
fig.add_trace(
    go.Bar(x=[1.2.3], y=[5.10.15]),
    row=1, col=1  # 1 * 1
)

fig.add_trace(
    go.Scatter(x=[20.30.40], y=[60.70.80]),
    row=1, col=2  # 1 * 2
)

fig.add_trace(
    go.Scatter(x=[50.60.70], y=[110.120.130]),
    row=2, col=1  2 * # 1
)
fig.add_trace(
    go.Bar(x=[50.60.70], y=[110.120.130]),
    row=2, col=2  # 2 * 2
)

fig.update_layout(height=600, 
                  width=800, 
                  title_text="Subgraph making")
fig.show()
Copy the code

Multiple subgraph title Settings

Many times we name each subtitle, which is implemented by subplot_titles

fig = make_subplots(rows=2, cols=2,
                    start_cell="bottom-left".# 'bottom-left', 'top-left
                    subplot_titles=[Figure 1 "son"."Child figure 2"."Child figure 3"."Child figure 4"]  The name of each subgraph
                   )  

Add 4 data tracks
fig.add_trace(
    go.Bar(x=[1.2.3], y=[5.10.15]),
    row=1, col=1  # 1 * 1
)

fig.add_trace(
    go.Scatter(x=[20.30.40], y=[60.70.80]),
    row=1, col=2  # 1 * 2
)

fig.add_trace(
    go.Scatter(x=[50.60.70], y=[110.120.130]),
    row=2, col=1  2 * # 1
)
fig.add_trace(
    go.Bar(x=[50.60.70], y=[110.120.130]),
    row=2, col=2  # 2 * 2
)

fig.update_layout(height=600, 
                  width=800, 
                  title_text="Multi-row and multi-column subgraph making")
fig.show()
Copy the code

Annotations

We can also add annotations to the data in the subgraph:

fig = make_subplots(rows=1, cols=2,
                    subplot_titles=[Figure 1 "son"."Child figure 2"]  # subgraph name
                   )  

# add data
fig.add_trace(
    go.Bar(x=[1.2.3], 
           y=[5.10.15],
           text=["Text 1"."Text 2"."Three words"].# Tag content
           textposition="inside"    # position
          ),
    row=1, col=1  # 1 * 1
)

# add data
fig.add_trace(
    go.Scatter(x=[1.2.3], 
           y=[5.10.15],
           mode="markers+text".# Scatter chart data display form
           text=["Text 4"."Text 5".Text "6"].# Tag content
           textposition="bottom center"    # position
          ),
    row=1, col=2  # 1 * 2
)


fig.update_layout(height=600, 
                  width=800, 
                  title_text="Add annotation to multi-subgraph")
fig.show()
Copy the code

Subgraph width Settings

Column_widths the subgraphs above are all of the same size and can be set to display different sizes with the parameter: column_widths

fig = make_subplots(rows=1, 
                    cols=2,
                    column_widths=[0.35.0.65].# Important: width ratio of two subgraphs
                    subplot_titles=[Figure 1 "son"."Child figure 2"]  # the name
                   )  

fig.add_trace(
    go.Bar(x=[1.2.3], 
           y=[5.10.15],
           text=["Text 1"."Text 2"."Three words"].# Tag content
           textposition="inside"    # position
          ),
    row=1, col=1  # 1 * 1
)

# add data
fig.add_trace(
    go.Scatter(x=[1.2.3], 
           y=[5.10.15],
           mode="markers+text".# Scatter chart data display form
           text=["Text 4"."Text 5".Text "6"].# Tag content
           textposition="bottom center"    # position
          ),
    row=1, col=2  # 1 * 2
)

fig.update_layout(height=600, 
                  width=800, 
                  title_text="Add annotation to multi-subgraph")
fig.show()
Copy the code

Sharing the x axis

Sharing the X-axis refers to sharing the X-axis for multiple figures in the same column and row:

fig = make_subplots(rows=3, 
                    cols=1.# Key parameters
                    shared_xaxes=True.Set the shared X-axis
                    vertical_spacing=0.03.# The size of the gap between the graphs
                    subplot_titles=[Figure 1 "son"."Child figure 2"."Child figure 3"]  # the name
                   )  

fig.add_trace(
    go.Bar(x=[1.2.3], 
           y=[5.10.15],
           text=["Text 1"."Text 2"."Three words"], 
           textposition="inside"    # position
          ),
    row=1, col=1  # 1 * 1
)

# add data
fig.add_trace(
    go.Scatter(x=[4.5.6], 
           y=[5.10.15],
           mode="markers+text",  
           text=["Text 4"."Text 5".Text "6"],  
           textposition="bottom center"    
          ),
    row=2, col=1  2 * # 1
)


# add data
fig.add_trace(
    go.Scatter(x=[10.20.30], 
           y=[25.30.45],
           mode="markers+text".# Scatter chart data display form
           text=[Text "7"."Text 8".Text "9"].# Tag content
           textposition="bottom center"    # position
          ),
    row=3, col=1  # 3 * 1
)


fig.update_layout(height=600, 
                  width=1000, 
                  title_text="Add annotation to multi-subgraph")
fig.show()
Copy the code

Shared y

Sharing the Y-axis refers to sharing the Y-axis for multiple figures in the same row:

fig = make_subplots(rows=2, cols=2.# 2 * 2
                    subplot_titles=[Figure 1 "son"."Child figure 2"."Child figure 3"."Child figure 4"],
                    shared_yaxes=True  # Important: Share the Y-axis
                   )

fig.add_trace(go.Scatter(x=[1.2.3], y=[2.3.4]),  # Data for two axes
              row=1, col=1)  # row position

fig.add_trace(go.Scatter(x=[20.30.40], y=[5.6.7]),
              row=1, col=2)

fig.add_trace(go.Bar(x=[20.30.40], y=[20.40.10]),
              row=2, col=1)

fig.add_trace(go.Scatter(x=[40.50.60], y=[70.80.90]),
              row=2, col=2)

fig.update_layout(height=600, width=600,
                  title_text="Multiple subgraphs share the Y-axis.")
fig.show()
Copy the code

Axis customization

from plotly.subplots import make_subplots
import plotly.graph_objects as go


fig = make_subplots(
    rows=2, 
    cols=2, 
    subplot_titles=("Plot 1"."Plot 2"."Plot 3"."Plot 4"))Add different data
fig.add_trace(go.Scatter(x=[1.2.3], 
                         y=[4.5.6]), 
              row=1, col=1)

fig.add_trace(go.Scatter(x=[20.30.40], 
                         y=[50.60.70]), 
              row=1, col=2)
fig.add_trace(go.Scatter(x=[300.400.500], 
                         y=[600.700.800]), 
              row=2, col=1)

fig.add_trace(go.Scatter(x=[4000.5000.6000], 
                         y=[7000.8000.9000]), 
              row=2, col=2)

# Customize the X-axis
fig.update_xaxes(title_text="Xaxis - 1 title", row=1, col=1)  # display normal
fig.update_xaxes(title_text="Xaxis - 2 title".range= [10.50], row=1, col=2)  # Set the range
fig.update_xaxes(title_text="Xaxis - 3 title", showgrid=False, row=2, col=1)  # do not display grid lines
fig.update_xaxes(title_text="Xaxis - 4 title".type="log", row=2, col=2)  # Log based

# Customize the Y-axis
fig.update_yaxes(title_text="Yaxis 1 heading", row=1, col=1)
fig.update_yaxes(title_text="Yaxis 2 title".range= [40.80], row=1, col=2)
fig.update_yaxes(title_text="Yaxis 3 title", showgrid=False, row=2, col=1)
fig.update_yaxes(title_text="Yaxis 4 title", row=2, col=2)

# Update title and height
fig.update_layout(title_text="Customize subgraph axis coordinates", height=700)

fig.show()
Copy the code

Shared color axis

The parameter used is colorAxis

fig = make_subplots(rows=1, cols=2, 
                    shared_yaxes=True)   # shared in the y direction

fig.add_trace(go.Bar(x=[1.2.3], y=[4.5.6],
                    marker=dict(color=[4.5.6],
                                coloraxis="coloraxis")),
              1.1)  The position is (1,1)

fig.add_trace(go.Bar(x=[1.2.3], y=[2.3.5],
                    marker=dict(color=[2.3.5],
                                coloraxis="coloraxis")),
              1.2) # position at (1,2)

fig.update_layout(coloraxis=dict(colorscale='Bluered'),   Color # shaft
                  showlegend=False)  # do not display legends

fig.show()
Copy the code

Subgraph position customization

The location of the subgraph is customized using the spec parameter, which is a 2-dimensional collection of lists containing rows and cols.

For example, if we want to draw a 2 by 2 graph, but there are only three graphs, then one graph must occupy two rows and one column, or one row and two columns.

fig = make_subplots(
    rows=2, cols=2,
    specs=[[{}, {}],  # 1 * 1, 1 * 2
           [{"colspan": 2}, None]],  The # 2*1 position occupies two columns, and the 2*2 position has no graph
    subplot_titles=(Figure 1 "son"."Child figure 2"."Child figure 3"))

fig.add_trace(go.Scatter(x=[1.2], y=[5.6]),
                 row=1, col=1) # 1 * 1

fig.add_trace(go.Scatter(x=[4.6], y=[8.9]),
                 row=1, col=2)  # 1 * 2

fig.add_trace(go.Scatter(x=[1.2.3], y=[2.5.2]),
                 row=2, col=1)  # 2*1 takes up two lines

fig.update_layout(showlegend=False.# do not display legends
                  title_text="Subgraph position customization")
fig.show()
Copy the code

fig = make_subplots(
    rows=2, cols=2,
    specs=[[{"rowspan":2}, {},# 1 times 1 occupies two columns,1 times 2
           [None{}]],The # 2*1 position does not have a graph
    subplot_titles=(Figure 1 "son"."Child figure 2"."Child figure 3"))

fig.add_trace(go.Scatter(x=[1.2], y=[5.6]),
                 row=1, col=1) # 1*1 occupies two columns

fig.add_trace(go.Scatter(x=[4.6], y=[8.9]),
                 row=1, col=2)  # 1 * 2

fig.add_trace(go.Scatter(x=[1.2.3], y=[2.5.2]),
                 row=2, col=2)  2 * # 1

fig.update_layout(showlegend=False.# do not display legends
                  title_text="Subgraph position customization")
fig.show()
Copy the code

Let’s look at a more complicated example:

fig = make_subplots(
    rows=5, cols=2.# 5*2 graphics
    specs=[[{}, {"rowspan": 2}].1 * 1 #; The 2*1 position takes up two rows
           [{}, None].# 2 * 1; The 2 by 2 position is already taken by the 2 by 1 up here
           [{"rowspan": 2."colspan": 2}, None].The # 3*1 position takes up 2 rows and 2 columns, so the two columns of row 3 and 4 only have a single figure
           [None.None],
           [{}, {}]]  # 5 * 1; 5 * 2
)

fig.add_trace(go.Scatter(x=[1.2], y=[1.2], name="(1, 1)"), row=1, col=1)

fig.add_trace(go.Scatter(x=[1.2], y=[1.2], name="(1, 2)"), row=1, col=2)

fig.add_trace(go.Scatter(x=[1.2], y=[1.2], name="(2, 1)"), row=2, col=1)

fig.add_trace(go.Scatter(x=[1.2], y=[1.2], name="(3, 1)"), row=3, col=1)

fig.add_trace(go.Scatter(x=[1.2], y=[1.2], name="(5, 1)"), 5.1) # row and col can be omitted
fig.add_trace(go.Scatter(x=[1.2], y=[1.2], name="(5, 2)"), 5.2)

fig.update_layout(height=600, 
                  width=600, 
                  title_text="Multiple subgraph location customization")

fig.show()
Copy the code

Subgraph type user-defined

The types of graphs available for subgraphs:

  • “Xy “: 2d scatter, bar chart, etc

  • “Scene “: the three-dimensional scatter3D, spherical cone

  • “Polar “: Polar coordinates such as scatterPolar, Barpolar, etc

  • “Ternary “: A ternary figure is the scatternary

  • “Mapbox “: the map is scattermapbox

  • “Domain “:. For graphs with certain fields, such as pie, Parcoords, parcats,

from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(
    rows=2, cols=2,
    specs=[[{"type": "xy"}, {"type": "polar"}],
           [{"type": "domain"}, {"type": "scene"}]],  # specify the type by type
)

fig.add_trace(go.Bar(y=[2.3.1]),
              1.1)

fig.add_trace(go.Barpolar(theta=[0.45.90], r=[2.3.1]),
              1.2)

fig.add_trace(go.Pie(values=[2.3.1]),
              2.1)

fig.add_trace(go.Scatter3d(x=[2.3.1], y=[0.0.0],
                           z=[0.5.1.2], mode="lines"),
              2.2)

fig.update_layout(height=700, showlegend=False)

fig.show()
Copy the code

Use of multiple subgraph types and positions:

from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(
    rows=2, cols=2,
    specs=[[{"type": "xy"}, {"type": "polar"}].# set type
           [{"colspan":2."type": "domain"},None]], # set position: 2*1 occupies two columns; 2 by 2 has no graphics
)

fig.add_trace(go.Bar(y=[2.3.1]),
              1.1)

fig.add_trace(go.Barpolar(theta=[0.45.90], r=[2.3.1]),
              1.2)

fig.add_trace(go.Pie(values=[2.3.1]),
              2.1)  # 

fig.update_layout(height=700, showlegend=False)

fig.show()
Copy the code

Parameter interpretation

Finally, attach the official website address, learn more: plotly.com/python/subp…

plotly.subplots.make_subplots(rows=1.The column and column values determine the position
                              cols=1, 
                              shared_xaxes=False.# share the xy axis
                              shared_yaxes=False, 
                              start_cell='top-left'.# Position of the first graph
                              print_grid=False.Whether to print table parameters
                              horizontal_spacing=None.# Spacing between vertical and horizontal directions
                              vertical_spacing=None, 
                              subplot_titles=None.# Subgraph title
                              column_widths=None.# column width and row height
                              row_heights=None, 
                              specs=None.# Subgraph type
                              insets=None.# 
                              column_titles=None.# Row and column headings
                              row_titles=None, 
                              x_title=None.# xy axis axis title
                              y_title=None, 
                              figure=None, 
                              **kwargs)
Copy the code

View the help documentation as follows:

from plotly.subplots import make_subplots
help(make_subplots)
Copy the code