как отобразить много категорий с помощью matplotlib?

#python #pandas #matplotlib

Вопрос:

Рассмотрим пример ниже

 dfa = pd.DataFrame({'type' : ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q'],
                   'value' : [2,3,4,2,5,3,6,5,3,1,3,5,7,5,3,5,4],
                   'date' : [pd.to_datetime('2021-01-01')]*17})

dfa
Out[337]: 
   type  value       date
0   a    2     2021-01-01
1   b    3     2021-01-01
2   c    4     2021-01-01
3   d    2     2021-01-01
4   e    5     2021-01-01
5   f    3     2021-01-01
6   g    6     2021-01-01
7   h    5     2021-01-01
8   i    3     2021-01-01
9   j    1     2021-01-01
10  k    3     2021-01-01
11  l    5     2021-01-01
12  m    7     2021-01-01
13  n    5     2021-01-01
14  o    3     2021-01-01
15  p    5     2021-01-01
16  q    4     2021-01-01
 

Как вы можете видеть, у меня (слишком) много категорий, но мне все равно нужно отобразить их все одновременно. Я пытался использовать hatch аргумент в matplotlib , но, похоже, это не затеняет некоторые шаблоны, а не другие (так что больше категорий визуально различаются).

 dfa.set_index(['date','type']).unstack().plot.bar(stacked = True, hatch = 'o')
 

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

Что я могу здесь сделать?
Спасибо!

Ответ №1:

Вы можете перебирать сгенерированные столбцы и назначать уникальный шаблон штриховки для каждой отдельной группы. Вам нужно будет снова сгенерировать легенду, чтобы она обновлялась с измененными столбцами.

Выбор bar.set_hatch(pattern * 2) вместо just bar.set_hatch(pattern) создаст шаблон, который в два раза плотнее. Смотрите демонстрацию штриховки для получения дополнительных примеров.

 import matplotlib.pyplot as plt
import pandas as pd

dfa = pd.DataFrame({'type': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'] * 2,
                    'value': [2, 3, 4, 2, 5, 3, 6, 5, 3, 1, 3, 5, 7, 5, 3, 5, 4,
                              3, 2, 2, 1, 5, 2, 7, 2, 3, 7, 5, 3, 5, 3, 5, 4, 3],
                    'date': [pd.to_datetime('2021-01-01')] * 17   [pd.to_datetime('2021-01-02')] * 17})
ax = dfa.set_index(['date', 'type']).unstack().plot.bar(stacked=True, rot=0)
hatch_patterns = ['/', '\', '|', '-', ' ', 'x', 'o', 'O', '.', '*', '/o', '\|', '|*', '-\', ' o', 'x*', 'o-', 'O|']
for bars, pattern in zip(ax.containers, hatch_patterns):
    for bar in bars:
        bar.set_hatch(pattern * 2)
ax.legend(bbox_to_anchor=(1.01, 1.01), loc='upper left')
plt.tight_layout()
plt.show()
 

график стека с индивидуальной штриховкой

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

1. действительно круто! Спасибо! можете ли вы просто объяснить, что это ax.containers такое и почему шаблоны умножаются на 2 раза?

2. ax.containers где matplotlib хранит группы столбцов, которые были созданы ранее. Умножение шаблона штриховки делает его более плотным (умножение строки похоже на ее повторение, поэтому 'x'*2 является 'xx' и в два раза плотнее 'x' ).