Search code examples
rggplot2plotly

How to make a stacked barplot with secondary y axis in R with ggplot and plotly?


I'm working with the following dataframe:

data <- data.frame('Tipo_de_Parto' = c("Cesário", "Vaginal",
                                       "Cesário", "Vaginal",
                                       "Cesário", "Vaginal",
                                       "Cesário", "Vaginal",
                                       "Cesário", "Vaginal"),
                   'Ano_do_Nascimento' = c("2019", "2019",
                                       "2020", "2020",
                                       "2021", "2021",
                                       "2022", "2022",
                                       "2023", "2023"),
                   'perc' = c(34.1, 65.9,
                           32.0, 68.0,
                           0.0, 0.0,
                           36.6, 63.4,
                           39.2, 60.8),
                   'n' = c(723, 1395,
                           587, 1247,
                           0, 0,
                           545, 943,
                           439, 681))

I'm trying to plot something like this:

enter image description here

How can I plot it in R with ggplot and then transform it to an interactive plot with ggplotly? 'Tipo_de_Parto' filling the bars, 'n' as primary y axis and 'perc' as secondary y axis. 'perc' should be plotted as a line, but it needs to be filtered to only "Vaginal".

I'm doing it for a HTML file.


Solution

  • Sorry just realized this question was in R. You could create this directly with Plotly in Python. I'm sure it should be very similar in R.

    import pandas as pd
    from plotly.subplots import make_subplots
    import plotly.graph_objects as go
    
    df = pd.DataFrame({'Tipo_de_Parto': ['Cesário', 'Vaginal', 'Cesário', 'Vaginal', 'Cesário', 'Vaginal', 'Cesário', 'Vaginal', 'Cesário', 'Vaginal'], 
                       'Ano_do_Nascimento': [2019, 2019, 2020, 2020, 2021, 2021, 2022, 2022, 2023, 2023], 
                       'perc': [0.341, 0.659, 0.32, 0.68, 0.0, 0.0, 0.366, 0.634, 0.392, 0.608], 
                       'n': [723, 1395, 587, 1247, 0, 0, 545, 943, 439, 681]})
    
    fig = make_subplots(specs=[[{"secondary_y": True}]])
    
    for t in df['Tipo_de_Parto'].unique():
        fig.add_trace(go.Bar(x=df['Ano_do_Nascimento'][df['Tipo_de_Parto']==t],
                             y=df['n'][df['Tipo_de_Parto']==t],
                             name=t),
                      secondary_y=False)
    
    fig.add_trace(go.Scatter(x=df['Ano_do_Nascimento']df['Tipo_de_Parto']=='Vaginal'], 
                         y=df['perc'][df['Tipo_de_Parto']=='Vaginal'], 
                         name='% Normal',
                         mode='lines+markers+text',
                         
                         ),
               secondary_y=True)
    
    fig.update_layout(yaxis2=dict(tickformat='.0%'))
    
    fig.write_html('fig.html')
    

    fig