Search code examples
pythonmatplotlibseabornline-plotxticks

Seaborn lineplot unexpected behaviour in the range of xticks


I am starting my studies on pandas and seaborn. I'm testing the lineplot, but the plot's x-axis does not show the range I expected for this attribute (num_of_elements). I expected that each value of this attribute shows up on the x-axis. Can someone explain what I'm missing on this plot? Thanks.

This is the code I'm using:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import ticker

df_scability = pd.DataFrame()

df_scability['num_of_elements'] = [13,28,43,58,73,88,93,108,123,138]
df_scability['time_minutes'] = [2,3,5,7,20,30,40,50,60,90]
df_scability['dataset'] = ['Top 10 users','Top 10 users','Top 10 users','Top 10 users','Top 10 users','Top 10 users',
                           'Top 10 users','Top 10 users','Top 10 users','Top 10 users']

dpi = 600
fig = plt.figure(figsize=(3, 2),dpi=dpi)
ax = sns.lineplot(x = "num_of_elements", y = "time_minutes", hue='dataset', err_style='bars', data = df_scability)

ax.legend(loc='upper left', fontsize=4)
sns.despine(offset=0, trim=True, left=True)
ax.yaxis.set_major_locator(ticker.MultipleLocator(10))
ax.set_yticklabels(ax.get_ymajorticklabels(), fontsize = 6)
ax.yaxis.set_major_formatter(ticker.ScalarFormatter())
ax.set_xticklabels(ax.get_xmajorticklabels(), fontsize = 6)
ax.xaxis.set_major_formatter(ticker.ScalarFormatter())
plt.ylabel('AVG time (min)',fontsize=7)
plt.xlabel('Number of elements',fontsize=7)
plt.tight_layout()

plt.show()

This code generates it as output for me: enter image description here


Solution

  • The line:

    sns.despine(offset=0, trim=True, left=True)
    

    removes the spines from plot, so it could cause confusion. The x axis is actually going from 6.75 to 144.25:

    print(ax.get_xlim())
    # (6.75, 144.25)
    

    But only ticks for 50 and 100 values are shown.
    So you can fix x axis range with:

    ax.set_xticks(range(0, 150 + 50, 50))
    

    before call the despine. 0 is the lowest tick, 150 the highest and 50 the step among ticks. You can tailor them on your needs.

    Complete Code

    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    from matplotlib import ticker
    
    df_scability = pd.DataFrame()
    
    df_scability['num_of_elements'] = [13,28,43,58,73,88,93,108,123,138]
    df_scability['time_minutes'] = [2,3,5,7,20,30,40,50,60,90]
    df_scability['dataset'] = ['Top 10 users','Top 10 users','Top 10 users','Top 10 users','Top 10 users','Top 10 users',
                               'Top 10 users','Top 10 users','Top 10 users','Top 10 users']
    
    dpi = 600
    fig = plt.figure(figsize=(3, 2),dpi=dpi)
    ax = sns.lineplot(x = "num_of_elements", y = "time_minutes", hue='dataset', err_style='bars', data = df_scability)
    
    ax.legend(loc='upper left', fontsize=4)
    ax.set_xticks(range(0, 150 + 50, 50))
    sns.despine(offset=0, trim=True, left=True)
    ax.yaxis.set_major_locator(ticker.MultipleLocator(10))
    ax.set_yticklabels(ax.get_ymajorticklabels(), fontsize = 6)
    ax.yaxis.set_major_formatter(ticker.ScalarFormatter())
    ax.set_xticklabels(ax.get_xmajorticklabels(), fontsize = 6)
    ax.xaxis.set_major_formatter(ticker.ScalarFormatter())
    plt.ylabel('AVG time (min)',fontsize=7)
    plt.xlabel('Number of elements',fontsize=7)
    plt.tight_layout()
    
    plt.show()
    

    enter image description here