Как сделать участок мозаики в Matplotlib

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

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

Наконец, как иметь мозаичный сюжет с 3 измерениями и возможные пустые категории?

Вот общий мозаичный сюжет (из википедии ) введите описание изображения здесь

One Solution collect form web for “Как сделать участок мозаики в Matplotlib”

Поскольку ничего не существует в python, вот код, который я сделал. Последнее измерение должно быть размером 1 (т. Е. Обычной таблицей) или 2 на данный момент. Не стесняйтесь обновлять код, чтобы исправить это, но может быть нечитабельно с более чем 3. Это немного долго, но это делает работу. Пример ниже.

Есть несколько вариантов, большинство из них самоочевидны, иначе:

  • dic_color_row : словарь, где ключи являются самым Index_1 индексом ( Index_1 в примере ниже), а значения – цветами, избегают черных / серых цветов
  • pad : пробел между каждой полосой графика
  • alpha_label : в третьем измерении используется альфа-трюк для дифференциации, между ними он будет отображаться как темно-серый / светло-серый в легенде, и вы можете изменить имя каждой метки (аналогично col_labels или row_labels )
  • color_label : добавить цвет фона к ярлыкам y-tick. [True / False]

     def mosaic_plot(df, dic_color_row, row_labels=None, col_labels=None, alpha_label=None, x_label=None, y_label=None, pad=0.01, color_ylabel=False): """ From a contingency table NxM, plot a mosaic plot with the values inside. There should be a double-index for rows eg 3 4 1 0 2 5 Index_1 Index_2 AA C 0 0 0 2 3 0 P 6 0 0 13 0 0 BB C 0 2 0 0 0 0 P 45 1 10 10 1 0 CC C 0 6 35 15 29 0 P 1 1 0 2 0 0 DD C 0 56 0 3 0 0 P 30 4 2 0 1 9 """ is_multi = len(df.index.names) == 2 fig, ax = plt.subplots(1,1, figsize=(len(df.columns), len(df.index.get_level_values(0).unique()))) size_col = df.sum().sort_values(ascending=False) df = df[size_col.index.values] if is_multi: inner_index = df.index.get_level_values(1).unique() prop_ii0 = (df.swaplevel().loc[inner_index[0]]/(df.swaplevel().loc[inner_index[0]] + df.swaplevel().loc[inner_index[1]])).fillna(0) alpha_ii = 0.5 true_y_labels = df.index.levels[0] else: alpha_ii = 1 true_y_labels = df.index prop_com = size_col.div(size_col.sum()) Yt = (df.groupby(level=0).sum().iloc[:,0].div(df.groupby(level=0).sum().iloc[:, 0].sum())+pad).cumsum() - pad Ytt = df.groupby(level=0).sum().iloc[:,0].div(df.groupby(level=0).sum().iloc[:, 0].sum()) x = 0 for j in df.groupby(level=0).sum()[size_col.index.values].iteritems(): bot = 0 S = float(j[1].sum()) for lab, k in j[1].iteritems(): bars = [] ax.bar(x, k/S, width=prop_com[j[0]], bottom=bot, color=dic_color_row[lab], alpha=alpha_ii, lw=0, align="edge") if is_multi: ax.bar(x, k/S, width=prop_com[j[0]]*prop_ii0.loc[lab, j[0]], bottom=bot, color=dic_color_row[lab], lw=0, alpha=1, align="edge") bot += k/S + pad x += prop_com[j[0]] + pad ## Aesthetic of the plot and ticks # Y-axis if row_labels == None: row_labels = Yt.index ax.set_yticks(Yt - Ytt/2) ax.set_yticklabels(row_labels) ax.set_ylim(0, 1 + (len(j[1]) - 1) * pad) if y_label == None: y_label = df.index.names[0] ax.set_ylabel(y_label) ax2 = ax.twiny() # X-axis if col_labels == None: col_labels = prop_com.index xticks = (prop_com + pad).cumsum() - pad - prop_com/2. ax.set_xticks(xticks) ax.set_xticklabels(col_labels) ax.set_xlim(0, prop_com.sum() + pad * (len(prop_com)-1)) ax2.set_xlim(*ax.get_xlim()) ax2.set_xticks(xticks) ax2.set_xticklabels(size_col.values.astype(int)) if x_label == None: x_label = df.columns.name ax.set_xlabel(x_label) ax2.set_xlabel("Size") # Ticks and axis settings ax2.tick_params(top=False, right=False, pad=0, length=0) ax.tick_params(top=False, right=False, pad=5) sns.despine(left=0, bottom=False, right=0, top=0, offset=3) # Legend if is_multi: if alpha_label == None: alpha_label = inner_index bars = [ax.bar(np.nan, np.nan, color="0.2", alpha=[1, 0.5][b]) for b in range(2)] plt.legend(bars, alpha_label, loc='center left', bbox_to_anchor=(1, 0.5), ncol=1, ) plt.tight_layout(rect=[0, 0, .9, 0.9]) if color_ylabel: for tick, label in zip(ax.get_yticklabels(), true_y_labels): tick.set_bbox(dict(pad=5, facecolor=dic_color_row[label])) return ax 

С помощью DataFrame вы получаете после перекрестной пересылки:

 df Index_1 Index_2 vwxyz AA Q 0 0 0 2 3 AA P 6 0 0 13 0 BB Q 0 2 0 0 0 BB P 45 1 10 10 1 CC Q 0 6 0 15 9 CC P 0 1 0 2 0 DD Q 0 56 0 3 0 DD P 30 4 2 0 1 

убедитесь, что у вас есть 2 столбца в качестве индекса:

 df.set_index(["Index_1", "Index_2"], inplace=True) 

а затем просто позвоните:

 mosaic_plot(df, {"AA":"r", "BB":"b", "CC":"y", "DD":"g"}, # dict of color, mandatory x_label='My Category', ) 

Это не идеально, но я надеюсь, что это поможет другим. mosaicplot python

  • морские временные ряды из панда данных
  • Шрифты по умолчанию в визуализации статистических данных Seaborn в iPython
  • Морские палитры - предотвращать рециркуляцию цветов
  • Как дать sns.clustermap предварительно вычисленную матрицу расстояний?
  • Настройка цвета фона в Seaborn
  • Координаты ящиков в Seaborn boxplot
  • Как добавить заголовок в Seaborn Facet Plot
  • Определение плотности двумерного ядра с помощью Python
  • Python - лучший язык программирования в мире.