Home > OS >  Matplotlib Deprecation Warning: specify the corners of the quadrilaterals with X and Y, or
Matplotlib Deprecation Warning: specify the corners of the quadrilaterals with X and Y, or

Time:04-29

I have the following code to create colorized price charts, here's an example of the output: Colorized chart

The code:

import numpy as np
import pandas as pd
from matplotlib.colors import ListedColormap
from matplotlib import pyplot as plt

def plot(ax: plt.Axes, df: pd.DataFrame, points: pd.Series, booleans: pd.Series, c1: list, c2: list):
    ncols = len(booleans)
    s = booleans.astype(object).replace({False: 0, True: 1})
    z = np.array(s).reshape(1, ncols)
    x = np.array(df.index)
    y = [points.min(), points.max()]
    N = 256
    vals = np.ones((N, 4))
    vals[:, 0] = np.linspace(c1[0], c2[0], N)
    vals[:, 1] = np.linspace(c1[1], c2[1], N)
    vals[:, 2] = np.linspace(c1[2], c2[2], N)
    newcmp = ListedColormap(vals)
    plt.rcParams['pcolor.shading'] = 'auto'
    ax.pcolormesh(x, y, z, alpha=0.2, cmap=newcmp)
    return ax

Full-disclosure, I don't understand how colormaps work in matplotlib, this code is slightly modified from another SO question.

The following error prints whenever I run this code, and nothing I've tried seems to fix the issue.

NOTE: The error does disappear after I try different solutions and I use importlib.reload() to reload the function in my jupyter notebook, but it always comes back later.

MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3. Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading']. This will become an error two minor releases later.

CodePudding user response:

The question is a bit hard to answer, as information is missing about how the array booleans is created and its meaning.

Supposing the booleans indicate some property of the line segments, it needs to be 1 shorter than the number of points (). You can use the default 'flat' shading (one flat color per cell in the mesh). In the code example below, the very last value in df['is ascending'] is dummy and can be removed for the colormesh.

import numpy as np
import pandas as pd
from matplotlib.colors import ListedColormap
from matplotlib import pyplot as plt

def plot(ax: plt.Axes, df: pd.DataFrame, points: pd.Series, booleans: pd.Series, c1: list, c2: list):
     s = booleans
     if len(s) == len(df):
          s = s[:-1]  # s needs to be one less than the number of values in the index
     z = np.array(s).reshape(1, -1)
     x = np.array(df.index)
     y = [points.min(), points.max()]
     N = 256
     newcmp = ListedColormap([c1, c2])
     ax.pcolormesh(x, y, z, alpha=0.2, cmap=newcmp, shading='flat')

N = 50
df = pd.DataFrame({'val': np.random.normal(1, 10, N).cumsum()   1000},
                  index=pd.date_range('20220101', periods=N, freq='D'))
df['is ascending'] = df['val'] > df['val'].shift(-1)

ax = df['val'].plot()
plot(ax, df, df['val'], df['is ascending'], 'limegreen', 'crimson')

colormesh indicating a segment property

If, on the other hand, booleans is a property of the points, a mesh with two rows and exactly the same number of columns as the number of points can be used. In that case, a 'gouraud' shading will take care of coloring per vertex.


def plot(ax: plt.Axes, df: pd.DataFrame, points: pd.Series, booleans: pd.Series, c1: list, c2: list):
     s = booleans
     z = np.tile(np.array(s), (2, 1))
     x = np.array(df.index)
     y = [points.min(), points.max()]
     N = 256
     newcmp = ListedColormap([c1, c2])
     ax.pcolormesh(x, y, z, cmap=newcmp, shading='gouraud')

N = 50
df = pd.DataFrame({'val': np.random.normal(1, 10, N).cumsum()   1000},
                  index=pd.date_range('20220101', periods=N, freq='D'))
df['is larger than mean'] = df['val'] > df['val'].mean()

ax = df['val'].plot()
plot(ax, df, df['val'], df['is larger than mean'], 'lightgreen', 'lightcoral')

coloring per point

  • Related