Home > Enterprise >  Changing colours crossing zero pyplot Python
Changing colours crossing zero pyplot Python

Time:05-20

I want to code a Pyplot graph where it changes colors below the negative mark. I have conditions stated at the Color Conditions section. how would i be able to get this to work?

import pandas as pd 
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.dates as mdates
from matplotlib.dates import DateFormatter

df = pd.DataFrame({'col1': [4, 5, 2, 2, 3, 5, 1, 1, 6],  
     'label':['Old','Old','Old','Old','Old','Old','Old','Old','Old'],
     'date': ['2022-01-24 10:07:02', '2022-01-27 01:55:03', '2022-01-30 19:09:03', '2022-02-02 14:34:06',
              '2022-02-08 12:37:03', '2022-02-10 03:07:02', '2022-02-10 14:02:03', '2022-02-11 00:32:25',
              '2022-02-12 21:42:03']})

CumSum_val = np.cumsum(df['col1'])
datetime = pd.to_datetime(df['date'])

#Color conditions
green_cond = np.where(CumSum_val > 0)
red_cond =  np.where(CumSum_val <= 0)

# Define the date format
date_form = DateFormatter("%m-%d")
plt.xaxis.set_major_formatter(date_form)

plt.plot(datetime[green_cond],CumSum_val[green_cond], color = 'g')
plt.plot(datetime[red_cond],CumSum_val[red_cond], color = 'r')

plt.show()

CodePudding user response:

You can try plot three lines with different color, the latter has prior priority to show color.

green_cond = CumSum_val > 0
red_cond =  CumSum_val <= 0

fig = plt.figure()
ax = fig.add_subplot(111)

ax.plot(datetime, CumSum_val, color='b')
ax.plot(datetime[green_cond], CumSum_val[green_cond], color='g')
ax.plot(datetime[red_cond], CumSum_val[red_cond], color='r')

# Define the date format
date_form = DateFormatter("%m-%d")
ax.xaxis.set_major_formatter(date_form)

plt.show()

enter image description here

CodePudding user response:

The data you provided doesn't cross zero, so I took the liberty to modify this value to a given threshold, 15 in the below example. You can change it to whatever value you like.

The idea is to insert a new point every time the line crosses the threshold. Linear interpolation was used to achieve it. Then, to properly plot the two lines you need to select the points with:

green_cond = CumSum_val >= threshold
red_cond =  CumSum_val <= threshold

Note that I used >= and <= because I want the lines to share the common threshold point.

import pandas as pd 
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.dates as mdates
from matplotlib.dates import DateFormatter, date2num, num2date

df = pd.DataFrame({'col1': [4, 5, 2, 2, 3, 5, 1, 1, 6],  
     'label':['Old','Old','Old','Old','Old','Old','Old','Old','Old'],
     'date': ['2022-01-24 10:07:02', '2022-01-27 01:55:03', '2022-01-30 19:09:03', '2022-02-02 14:34:06',
              '2022-02-08 12:37:03', '2022-02-10 03:07:02', '2022-02-10 14:02:03', '2022-02-11 00:32:25',
              '2022-02-12 21:42:03']})

def modify_coords(x, y, y_lim):
    """If a line segment defined by `(x1, y1) -> (x2, y2)` intercepts
    a limiting y-value, divide this segment by inserting a new point
    such that y_newpoint = y_lim.
    """
    xv, yv = [x[0]], [y[0]]
    for i in range(len(x) - 1):
        xc, xn = x[i:i 2]
        yc, yn = y[i:i 2]
        if ((yc < y_lim) and (yn > y_lim)) or ((yc > y_lim) and (yn < y_lim)):
            xv.append(((y_lim - yc) / ((yn - yc) / (xn - xc)))   xc)
            yv.append(y_lim)
        xv.append(xn)
        yv.append(yn)
    return np.array(xv), np.array(yv)

CumSum_val = np.cumsum(df['col1'])
datetime = pd.to_datetime(df['date'])
datenum = date2num(datetime)

threshold = 15
datenum, CumSum_val = modify_coords(datenum, CumSum_val, threshold)
datetime = np.array(num2date(datenum))

#Color conditions
green_cond = CumSum_val >= threshold
red_cond =  CumSum_val <= threshold

fig, ax = plt.subplots()

# Define the date format
date_form = DateFormatter("%m-%d")
ax.xaxis.set_major_formatter(date_form)

ax.plot(datetime[green_cond], CumSum_val[green_cond], color = 'g')
ax.plot(datetime[red_cond], CumSum_val[red_cond], color = 'r')

plt.show()

enter image description here

  • Related