I would greatly appreciate let me know how to plot a heatmap-like plot for categorical features?

In fact, based on this post, the association between categorical variables should be computed using Crammer's V. Therefore, I found the following code to plot it, but I don't know why he plotted it for "contribution", which is a numeric variable?

def cramers_corrected_stat(confusion_matrix):
    """ calculate Cramers V statistic for categorical-categorical association.
        uses correction from Bergsma and Wicher, 
        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)))
# there's probably a nice pandas way to do this
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 Correlation between Variables");

I also found Bokeh. However, I am not sure if it uses Crammer's V to plot the heatmap or not?

Really, I have two categorical features: the first one has 2 categories and the second one has 37 categories.

I need the plot will be like the two last plots presented here, but also display the association values on it too.
Thanks in advance.


2 Answers 2


It might not be useful to plot the relationship between categorical features. The visualization would imply an ordering to categorical values which might not lead to incorrect interpretations.

A more useful option might be a contingency table. One feature would be in the rows, another feature would be in the columns. The cells would be the counts of co-occurrence.


If your goal is to have a color representation of the contingency table then you can use pd.crosstab along with background_gradient like this:

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"])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.