Search code examples
pythonmatplotlibplot-annotations

How to remove NaN values from matshow 2D plot and format labels as percentages


I am plotting some 2D array data as a map with a color scale and I have some NaN values that I don't want to show up. I need these values to show up as plain white squares and for the formatting to be in percentage style. Here is what I have so far:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

filename = "data.csv"

df = pd.read_csv(filename, header=None)

fig, ax = plt.subplots()
ax.matshow(df, cmap='bwr')

for (i, j), z in np.ndenumerate(df):
    ax.text(j, i, '{:0.1f}'.format(z), ha='center', va='center',
            bbox=dict(boxstyle='round', facecolor='white', edgecolor='0.3'))

plt.show()

This is the data I have:

enter image description here

...and here is what I get out right now. This is almost exactly what I want, except for those NaN values and the percentage formatting.

enter image description here

Any help would be very much appreciated.


Solution

  • import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    
    # sample data
    np.random.seed(365)
    df = pd.DataFrame(np.random.random((4, 4)))
    df.iloc[2, -1] = np.nan
    df.iloc[3, 2:] = np.nan
    
    # plot
    fig, ax = plt.subplots()
    ax.matshow(df, cmap='bwr')
    
    for (i, j), z in np.ndenumerate(df):
        if np.isnan(z):
            z = ''  # if z is nan make it an empty string
        else:
            z = f'{z*100:0.1f}%'  # otherwise multiply by 100 and string format
        ax.text(j, i, z, ha='center', va='center',
                bbox=dict(boxstyle='round', facecolor='white', edgecolor='0.3'))
    
    plt.show()
    

    enter image description here