Home > Blockchain >  Matplotlib\Seaborn wrong colors on float data with custom colormap
Matplotlib\Seaborn wrong colors on float data with custom colormap

Time:05-16

Values lower and equal 1000/60 (16.6667) must have gradient from blue to green. Values greater than 1000/60 (16.6667) must have gradient from red to black. But values from 16.67 to 16.70 are blue instead red. Why? How make them red?

example image

import glob
import os
import subprocess
import sys

import matplotlib.colors
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from PIL import Image, ImageEnhance, ImageChops, ImageDraw, ImageFilter

Image.MAX_IMAGE_PIXELS = None
pd.options.display.float_format = '{:.2f}'.format
np.set_printoptions(suppress=True, precision=2)

# Open image in end
def openImage(path):
    imageViewerFromCommandLine = {'linux': 'xdg-open',
                                  'win32': 'explorer',
                                  'darwin': 'open'}[sys.platform]
    subprocess.run([imageViewerFromCommandLine, path])


test_data = np.arange(16.60, 16.81, 0.01)
test_data = np.resize(test_data, (3, 7))

line_legend = (1000 / 29, 16.66, 16.00, 0)
line_legend_last = len(line_legend) - 1

# norm for colormap from 0 to 1000/29
norm = matplotlib.colors.Normalize(line_legend[line_legend_last], line_legend[0], clip=True)

# custom colors
colors = [[0.0, "lime"],
          [norm(16.00), "green"],
          [norm(16.66), "blue"],
          [norm(16.67), "red"],
          [1.0, "black"]]
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", colors)

# color bar range and labels
cbar_kws = {"orientation": "vertical",
            "shrink": 1,
            'extend': 'both',
            "ticks": line_legend,
            "drawedges": False,
            }

ax = sns.heatmap(test_data, linewidths=0.1, linecolor='gainsboro', cmap=cmap, xticklabels=1, yticklabels=1, square=True,
                 cbar=True, annot=True, fmt='g', cbar_kws=cbar_kws, robust=True,
                 vmin=line_legend[line_legend_last], vmax=line_legend[0])

plt.savefig(r'D:\result_wrong_colors.png')

openImage(r'D:\result_wrong_colors.png')

Image Result

CodePudding user response:

Internally, the colormap is represented by a list of colors. Default, there are 256 colors in that list. LinearSegmentedColormap.from_list has a parameter N= to set a different number of colors. Depending on how precise you need the color ranges to be, you'd need a larger number.

cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", colors, N=10000)

LinearSegmentedColormap with 10000 colors

  • Related