Построение категориальной диаграммы рассеяния в seaborn или matplotlib

#python #pandas #matplotlib #seaborn

#python #панды #matplotlib #seaborn

Вопрос:

У меня есть следующий фрейм данных

    it, A   B   C   D
0  10, aa  mn  cd  kk
1  100, ab  cd  wc  ll
2  1000, wc  cd  mn  sf
3  10000, ll  ll  kk  mn
4  100000, wc  kk  mn  cd
5  1000000, aa  ll  we  sf
6  10000000, ss  aa  ss  kk
  

создан как

 options = ["ab", "cd", "bb", "aa", "we", "ss", "kk", "mn", "re", "wc", "ll", "sf"]
df = pd.DataFrame(columns=["A", "B", "C", "D"])
for i, it in enumerate([1,2,3,4,5,6,7]):
    row = [10**i, random.sample(options, 1)[0], random.sample(options, 1)[0], 
           random.sample(options, 1)[0], random.sample(options, 1)[0]]
    df.loc[i] = row
  

Цель состоит в том, чтобы создать диаграмму рассеяния, где по оси y представлены уникальные значения из фрейма данных в отсортированном порядке, например, параметры, а ось a соответствует столбцу. it
Теперь в зависимости от того, принадлежат ли данные столбцу A, B, C, , или D я хочу по-разному раскрасить точки рассеяния и указать легенду. Итак, я знаю, из какого класса происходит точка.

Как мне это сделать в seaborn или matplotlib?

То, как я делаю это в matplotlib,

 iters = list(range(df.shape[0]))
x, y = sort(iters, df["A"])
plt.scatter(x, y, color="red")
x, y = sort(iters, df["B"])
plt.scatter(x, y, color="blue")
...
  

но это сортирует не всю ось y, а только метки, принадлежащие отдельным столбцам.

Ответ №1:

Давайте попробуем сложить данные, преобразовать в категориальный с заданным порядком, отсортировать и построить график:

 s = df.stack() 

s = pd.Series(pd.Categorical(s, categories=options, ordered=True),
              index=s.index)

sns.scatterplot(data=s.sort_values().reset_index(name='value'),
                x='level_0', y='value', hue='level_1'
               )
  

Вывод:

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


Обновление: если у вас есть столбец xvalue и вам нужны только некоторые столбцы ['A','B','C','D'] , используйте melt вместо stack :

 s = df.melt(id_vars='xvalue', 
            value_vars=['A','B','C','D'],
            value_name='value',
            var_name='column')
s['value'] = pd.Categorical(s['value'], categories=options, ordered=True)

sns.scatterplot(data=s.sort_values('value'),
                x='xvalue', y='value', hue='column'
               )
  

Комментарии:

1. Но это не выглядит отсортированным! ось x должна быть осью y, но это не большая проблема. Проблема в том, что ось x не отсортирована, по крайней мере, для matplotlib

2. @YohanRoth Я пропустил options часть. Смотрите Обновленный ответ.

3. итак, ваше решение не работает в моем случае, это моя вина, я неправильно указал проблему. в дополнение к столбцу A, B, C, D у меня есть еще один столбец, в котором указаны значения по оси x, которые не являются просто строками (у них большие пробелы, такие как 1, 10, 1000, 10000) и т.д. Не могли бы вы показать мне, как изменить ответ, чтобы учесть это? В любом случае я приму это! Я обновил проблему

4. Я получаю ошибку ValueError: длина значений (3) не соответствует длине индекса (28) для s[‘value’] = pd.Categorical(s, categories= options, ordered= True)

5. s.shape (28, 3) pd.Категориальный (3,)