Matplotlib/Seaborn shareX создает неправильные метки x для всех подграфиков со строковыми значениями оси x

Я создаю графики подзаголовков, используя цикл for, и когда я включаю «sharex», метки x для всех подзаголовков неверны и соответствуют последнему подзаголовку. Я хочу, чтобы он создавал галочку для каждой доступной метки.

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')

Я специально сделал фрейм данных, поэтому параметр O1 имеет значение 1 для всех «букв». То же самое для O2, O3 и O4.

При отключенном shareX (ложь):
С отключенным shareX

При включенном shareX (True):
При включенном ShareX

Обратите внимание, что значения не соответствуют параметрам правильно, есть только 3 метки, и все подграфики соответствуют последнему порядку подграфиков, когда shareX был выключен.

Это проблема со строковыми осями X. Если я изменяю столбец «Параметры» на числовые значения, все работает нормально. См. здесь:
целочисленные значения оси x

Есть ли способ создать подграфики с помощью циклов for, включить ShareX и иметь четыре метки, O1, O2, O3, O4, и все значения правильно выровнены?


person JoshS    schedule 12.10.2018    source источник


Ответы (1)


К сожалению, в настоящее время нет возможности заранее определить единицы измерения осей. Это делает построение нескольких категориальных наборов данных громоздким.
Один хитрый обходной путь – нанести что-то на оси в ожидаемом порядке, а затем удалить это. Это делается с помощью функции prepare_axes в приведенном ниже коде.

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()

введите здесь описание изображения

person ImportanceOfBeingErnest    schedule 13.10.2018