Search code examples
python-3.xplotlyscatter-plotpolar-coordinates

Using Facet_col with Plotly Express Scatter_Polar charts


Is it possible to use the facet_col or facet_row option when using px.scatter_polar? I have tried, but get “TypeError: scatter_polar() got an unexpected keyword argument ‘facet_col’”.

import plotly.express as px
import pandas as pd

df=pd.DataFrame({'WD': {0: 'N', 1: 'N', 2: 'N', 3: 'N', 4: 'N', 5: 'N', 6: 'NNE', 7: 'NNE', 8: 'NNE', 9: 'NNE', 10: 'NNE', 11: 'NNE'}, 'WS': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 1, 7: 2, 8: 3, 9: 4, 10: 5, 11: 6}, 'Lines': {0: 0, 1: 3, 2: 5, 3: 12, 4: 1, 5: 0, 6: 0, 7: 1, 8: 4, 9: 5, 10: 2, 11: 0}, 'Site': {0: 'EQ21301', 1: 'EQ21309', 2: 'EQ21301', 3: 'EQ21306', 4: 'EQ21301', 5: 'EQ21301', 6: 'EQ21301', 7: 'EQ21301', 8: 'EQ21306', 9: 'EQ21306', 10: 'EQ21306', 11: 'EQ21309'}})
fig = px.scatter_polar(df, r="WS", theta="WD",size='Lines',facet_col='Site',
                       color='WS',color_discrete_sequence=px.colors.sequential.YlOrRd,template='plotly_dark') 


fig.show()

I know I can create it with make_subplots, but thought this method might be nicer and means I don't have to add extra code every time the number of Sites increases.


Solution

    • simply it's not a capability...
    • use plotly express to generate a figure as base for getting parameters
    • make_subplots() for each Site
    • copy across wanted parameters from trace
    • copy across wanted parameters from layout
    import plotly.express as px
    import plotly.graph_objects as go
    import pandas as pd
    from plotly.subplots import make_subplots
    
    df=pd.DataFrame({'WD': {0: 'N', 1: 'N', 2: 'N', 3: 'N', 4: 'N', 5: 'N', 6: 'NNE', 7: 'NNE', 8: 'NNE', 9: 'NNE', 10: 'NNE', 11: 'NNE'}, 'WS': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 1, 7: 2, 8: 3, 9: 4, 10: 5, 11: 6}, 'Lines': {0: 0, 1: 3, 2: 5, 3: 12, 4: 1, 5: 0, 6: 0, 7: 1, 8: 4, 9: 5, 10: 2, 11: 0}, 'Site': {0: 'EQ21301', 1: 'EQ21309', 2: 'EQ21301', 3: 'EQ21306', 4: 'EQ21301', 5: 'EQ21301', 6: 'EQ21301', 7: 'EQ21301', 8: 'EQ21306', 9: 'EQ21306', 10: 'EQ21306', 11: 'EQ21309'}})
    # create px figure to copy formatting from
    fig = px.scatter_polar(df, r="WS", theta="WD",size='Lines',
                           color='WS',color_discrete_sequence=px.colors.sequential.YlOrRd,template='plotly_dark') 
    
    
    # make sub-plots for all "Site"
    spfig = make_subplots(
        cols=len(df["Site"].unique()),
        specs=[[{"type": "polar"} for s in df["Site"].unique()]],
        subplot_titles=df["Site"].unique()
    )
    # use base go capability and copy wanted parameters from px trace
    for c, site in enumerate(df["Site"].unique()):
        dft = df.loc[df["Site"].eq(site)]
        spfig.add_trace(
            go.Scatterpolar(
                {
                    **fig.to_dict()["data"][0],
                    **{
                        "r": dft["WS"],
                        "theta": dft["WD"],
                        "name": site,
                        "marker": {
                            **fig.to_dict()["data"][0]["marker"],
                            **{"size": dft["Lines"], "color": dft["WS"]},
                        },
                    },
                },
            ),
            row=1,
            col=c + 1,
        )
    
    # finally copy across layout parameters
    spfig = spfig.update_layout({ **fig.to_dict()["layout"], **spfig.to_dict()["layout"]})
    spfig.layout.template = fig.layout.template
    for axis in ["polar","polar2","polar3"]:
        spfig.layout[axis]["angularaxis"] = fig.layout.polar["angularaxis"]
        
    # and we're done...
    spfig
    

    enter image description here