简体   繁体   中英

Matplotlib/Seaborn shareX creates wrong x-labels for all subplots with string x-axis values

I am creating subplot graphs using a for loop and when I turn on 'sharex', the x-labels for all the subplots are incorrect and match the last subplot. I want it to create a tick for each available label.

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


df = pd.DataFrame({
     'letters' : ['A','A','A', 'B','B','B', 'C','C','C', 'D','D','D'],
     'values' : [1, 2, 3, 3, 2, 1, 2, 3, 1, 2, 3, 4],
     'options': ['O 1', 'O 2', 'O 3', 'O 3', 'O 2', 'O 1',
                 'O 2','O 3','O 1','O 2','O 3','O 4'],
                 })

list_letters = ['A', 'B', 'C', 'D']

fig,axes = plt.subplots(nrows = 1, ncols = len(list_letters), sharey = True, sharex = True)
for letter in list_letters:
    index = list_letters.index(letter)
    df2 = df[(df['letters'] == letter)]
    sns.scatterplot(x="options", y="values",data = df2,
              hue = 'options', ax=axes[index], legend = False)

    axes[index].set_title(letter, rotation = 60, verticalalignment = 'bottom', ha = 'left')

I specifically made the dataframe so Option O1 has a value of 1 for all 'letters'. Same for O2, O3, and O4.

With shareX turned off (False):
关闭shareX

With shareX turned on (True):
启用shareX

Note how the values do not correspond correctly to the options, there are only 3 labels, and all the subplots match the last subplot order when shareX was off.

This is an issue with string x-axes. If I change 'options' column to numeric values, it all works fine. See here:
x轴整数值

Is there any way to create subplots through for-loops, have ShareX turned on, and have four labels, O1, O2, O3, O4, and all the values correctly line up?

Unfortunately, there is currently no way to predetermine the units of an axes. This makes plotting of multiple categorical datasets cumbersome.
One hacky workaround is to plot something to the axes in the expected order and remove it afterwards. This is done via the prepare_axes function in the code below.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({
     'letters' : ['A','A','A', 'B','B','B', 'C','C','C', 'D','D','D'],
     'values' : [1, 2, 3, 3, 2, 1, 2, 3, 1, 2, 3, 4],
     'options': ['O 1', 'O 2', 'O 3', 'O 3', 'O 2', 'O 1',
                 'O 2','O 3','O 1','O 2','O 3','O 4'],
                 })

list_letters = ['A', 'B', 'C', 'D']

def prepare_axes(x, ax):
    ax.autoscale(False)
    line, = ax.plot(x, np.zeros(len(x)))
    line.remove()
    ax.relim()
    ax.autoscale(True)

# determine all needed categoricals        
uniqueoptions = df["options"].unique()

fig,axes = plt.subplots(nrows = 1, ncols = len(list_letters), sharey = True, sharex = True)
for letter in list_letters:
    index = list_letters.index(letter)
    df2 = df[(df['letters'] == letter)]
    _, hue = np.unique(df2["options"].values, return_inverse=True)
    prepare_axes(uniqueoptions, axes[index])
    axes[index].scatter(x="options", y="values", c=hue, data = df2)

    axes[index].set_title(letter, rotation = 60, verticalalignment = 'bottom', ha = 'left')

plt.show()

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM