Как построить график, подобный тепловой карте, для категориальных признаков?

Вопрос или проблема

Я был бы очень признателен, если бы вы рассказали, как построить график, похожий на heatmap, для категориальных признаков?

На самом деле, согласно этому посту, связь между категориальными переменными следует вычислять с использованием V Крамера. Поэтому я нашел следующий код для его построения, но не понимаю, почему он построил его для “contribution”, который является числовой переменной?

def cramers_corrected_stat(confusion_matrix):
    """ вычисляет статистику V Крамера для ассоциации категориальных данных.
        использует коррекцию из работы Бергсма и Вичера, 
        Journal of the Korean Statistical Society 42 (2013): 323-328
    """
    chi2 = ss.chi2_contingency(confusion_matrix)[0]
    n = confusion_matrix.sum().sum()
    phi2 = chi2/n
    r,k = confusion_matrix.shape
    phi2corr = max(0, phi2 - ((k-1)*(r-1))/(n-1))    
    rcorr = r - ((r-1)**2)/(n-1)
    kcorr = k - ((k-1)**2)/(n-1)
    return np.sqrt(phi2corr / min( (kcorr-1), (rcorr-1)))

cols = ["Party", "Vote", "contrib"]
corrM = np.zeros((len(cols),len(cols)))
# возможно, есть более элегантный способ сделать это с помощью pandas
for col1, col2 in itertools.combinations(cols, 2):
    idx1, idx2 = cols.index(col1), cols.index(col2)
    corrM[idx1, idx2] = cramers_corrected_stat(pd.crosstab(df[col1], df[col2]))
    corrM[idx2, idx1] = corrM[idx1, idx2]

corr = pd.DataFrame(corrM, index=cols, columns=cols)
fig, ax = plt.subplots(figsize=(7, 6))
ax = sns.heatmap(corr, annot=True, ax=ax); ax.set_title("Cramer V Корреляция между переменными");

Я также нашел Bokeh. Однако я не уверен, использует ли он V Крамера для построения heatmap или нет?

На самом деле, у меня есть два категориальных признака: первый имеет 2 категории, а второй — 37 категорий.

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

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

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

Если ваша цель — получить цветное представление контингентной таблицы, то вы можете использовать pd.crosstab вместе с background_gradient, как это:

import pandas as pd

data = {
    'City': ['City1', 'City2', 'City1', 'City2', 'City1', 'City2', 'City3', 'City2', 'City1', 'City2', 'City1', 'City2', 'City3', 'City3', 'City1', 'City2', 'City1', 'City2', 'City1', 'City2'],
    'Sales': [100, 200, 200, 200, 100, 100, 400, 400, 500, 500, 100, 100, 200, 300, 400, 200, 400, 300, 100, 100]
}
df = pd.DataFrame(data)

df_cross = pd.crosstab(df["Sales"], df["City"])
df_cross.style.background_gradient(vmin=df_cross.values.min(),
                                   vmax=df_cross.values.max())

Ответ или решение

Для построения тепловой карты, отображающей ассоциации между категориальными переменными, вы можете следовать нескольким шагам. Я объясню, как использовать значение Cramér’s V для оценки ассоциации между переменными и как визуализировать эти ассоциации с помощью библиотеки Seaborn и Pandas в Python.

Шаг 1: Подготовьте данные

Предположим, у вас есть два категориальных признака. Например, первый имеет 2 категории, а второй — 37 категорий.

import pandas as pd

data = {
    'Category1': ['A', 'B', 'A', 'A', 'B', 'A', 'B', 'B', 'A', 'B'],
    'Category2': ['X', 'Y', 'X', 'Z', 'Y', 'X', 'Z', 'Y', 'X', 'Z']
}
df = pd.DataFrame(data)

Шаг 2: Создайте контингентную таблицу

Сначала создайте контингентную таблицу с помощью pd.crosstab(), которая показывает количество вхождений каждого сочетания категорий.

contingency_table = pd.crosstab(df['Category1'], df['Category2'])
print(contingency_table)

Шаг 3: Рассчитайте значение Cramér’s V

Теперь вы можете использовать функцию, представленную в вашем вопросе, для расчета значения Cramér’s V для этой таблицы.

import numpy as np
import scipy.stats as ss
import itertools

def cramers_corrected_stat(confusion_matrix):
    chi2 = ss.chi2_contingency(confusion_matrix)[0]
    n = confusion_matrix.sum().sum()
    phi2 = chi2 / n
    r, k = confusion_matrix.shape
    phi2corr = max(0, phi2 - ((k - 1) * (r - 1)) / (n - 1))
    rcorr = r - ((r - 1) ** 2) / (n - 1)
    kcorr = k - ((k - 1) ** 2) / (n - 1)
    return np.sqrt(phi2corr / min((kcorr - 1), (rcorr - 1)))

# Применение функции к контингентной таблице
cramers_v = cramers_corrected_stat(contingency_table.values)
print("Cramér's V:", cramers_v)

Шаг 4: Постройте тепловую карту

Для визуализации результатов создайте тепловую карту с помощью библиотеки Seaborn. Для этого используется контингентная таблица.

import seaborn as sns
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 7))
sns.heatmap(contingency_table, annot=True, fmt='d', cmap='coolwarm', cbar=True)
plt.title("Контингентная таблица с ассоциациями")
plt.xlabel("Категория 2")
plt.ylabel("Категория 1")
plt.show()

Альтернативный способ

Если вы хотите использовать стиль Pandas для визуализации контингентной таблицы с градиентом, вы можете сделать это следующим образом:

contingency_table.style.background_gradient(cmap='coolwarm')

Заключение

Подводя итог, использование Cramér’s V для анализа ассоциаций между категориальными переменными — это отличный способ количественно оценить эти отношения. Визуализация в виде тепловой карты помогает лучше понять распределение данных и взаимосвязи между категориями. Важно также помнить, что ассоциации не всегда указывают на причинно-следственные связи, поэтому интерпретируйте результаты с осторожностью.

Если у вас есть вопросы или нужны дальнейшие пояснения, не стесняйтесь спрашивать!

Оцените материал
Добавить комментарий

Капча загружается...