Search code examples
pythonmatplotlibseabornviolin-plot

How to plot points over a violin plot?


I have four pandas Series and I plot them using a violin plot as follows:

import seaborn
seaborn.violinplot([X1['total'], X2['total'], X3['total'], X4['total']])

I would like to plot the values on top of the violin plot so I added:

seaborn.stripplot([X1['total'], X2['total'], X3['total'], X4['total']])

But this gives:

enter image description here

It plots all the points over the first violin plot.

What am I doing wrong?


Solution

  • Currently (seaborn 0.12.1), sns.violinplot seems to accept a list of lists as data, and interprets it similar to a wide form dataframe. sns.striplot (as well as sns.swarmplot), however, interpret this as a single dataset.

    On the other hand, sns.stripplot accepts a dictionary of lists and interprets it as a wide form dataframe. But sns.violinplot refuses to work with that dictionary.

    Note that seaborn is being actively reworked internally to allow a wider set of data formats, so one of the future versions will tackle this issue.

    So, a list of lists for the violin plot, and a dictionary for the stripplot allows combining both:

    import seaborn as sns
    import pandas as pd
    import numpy as np
    
    X1, X2, X3, X4 = [pd.DataFrame({'total': np.random.normal(.1, 1, np.random.randint(99, 300)).cumsum()})
                      for _ in range(4)]
    
    ax = sns.violinplot([X1['total'], X2['total'], X3['total'], X4['total']], inner=None)
    sns.stripplot({0: X1['total'], 1: X2['total'], 2: X3['total'], 3: X4['total']},
                  edgecolor='black', linewidth=1, palette=['white'] * 4, ax=ax)
    

    combining sns.violinplot and sns.stripplot