0

I am using matplotlib to draw a plot. What I want to achieve is to connect points if one condition is met. For instance, if I have a dataframe like the following:

import os
import pandas as pd
import numpy as np

from matplotlib import pyplot as plt

df=pd.DataFrame({'dates': [2001, 2002, 2003, 2004, 2005, 2006], 'census_people': [306,327,352,478,250, 566], 'census_houses': [150,200,249,263, 180, 475]}) #I changed the dates from strings to ints

I could create plots like this use the following codes:

plt.plot('dates','census_houses',data=df[df['dates'] < 2004] ,marker='o',color='orange', linewidth=2)
plt.plot('dates','census_houses',data=df[df['dates'] > 2002] ,marker='o',color='orange', linewidth=2, linestyle = '--')

The plot is like the following:

enter image description here

However, what I truely want is, for instance, use the dashed line to connect points if the census_houses is bigger than 250. How to achieve this using matplotlib? Any suggestions and insights are welcomed! Thank you~

Bright Chang
  • 191
  • 2
  • 14

1 Answers1

1

This effect can be achieved by applying clipping paths. In this example I suppose the full line completely draws over the dashed line, so only clipping of the full line is needed.

In the example, the special value for the y-axis is set to 220, different colors and very thick lines are used, to better see what is happening. The parameters for Rectangle((x, y), width, height) are setting y to the desired cut-off value, x is some position far left, width makes sure that x + width is far right and height is a large positive number to clip above the line, negative to clip below the line.

This post has more information about clipping paths.

import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.patches import Rectangle

def do_clipping(patches, special_y, keep_below=True, ax=None):
    ax = ax or plt.gca()
    xmin, xmax = plt.xlim()
    ymin, ymax = plt.ylim()
    height = ymax - ymin
    if keep_below:
        height = -height
    clip_rect = Rectangle((xmin, special_y), xmax - xmin, height,
                          transform=ax.transData)
    for p in patches:
        p.set_clip_path(clip_rect)

df = pd.DataFrame({'dates': [2001, 2002, 2003, 2004, 2005, 2006],
                   'census_houses': [150, 200, 249, 263, 180, 475]})
plt.plot('dates', 'census_houses', data=df, color='limegreen', linewidth=10, linestyle='--')
plot_patches = plt.plot('dates', 'census_houses', data=df, color='crimson', linewidth=10)
do_clipping(plot_patches, 220)
plt.show()

example plot

JohanC
  • 71,591
  • 8
  • 33
  • 66
  • Thank you very much for your reply! The solution is well received! I will try to apply your codes to my own problems... – Bright Chang Jan 04 '20 at 06:00