pandas boxplot contains content of plot saved before

Viewed 159

I'm plotting some columns of a datafame into a boxplot. Sofar, no problem. As seen below I wrote some stuff and it works. BUT: the second plot contains the plot of the first plot, too. So as you can see I tried it with "= None" or "del value", but it does not work. Putting the plot function outside also don't solves the problem.

Whats wrong with my code?

Here is an executable example

 import pandas as pd 
 
 d1 = {'ff_opt_time': [10, 20, 11, 5, 15 , 13, 19, 25  ], 'ff_count_opt': [30, 40, 45, 29, 35,38,32,41]}
 df1 = pd.DataFrame(data=d1)
 d2 = {'ff_opt_time': [1, 2, 1, 5, 1 , 1, 4, 5  ], 'ff_count_opt': [3, 4, 4, 9, 5,3, 2,4]}
 df2 = pd.DataFrame(data=d2)
 
 def evaluate2(df1, df2):
    
     def plot(df, output ):
         boxplot = df.boxplot(rot=45,fontsize=5)
         fig = boxplot.get_figure()
         fig.savefig(output + ".pdf")
     
     df_ot = pd.DataFrame(columns=['opt_time1' , 'opt_time2'])
     df_ot['opt_time1'] = df1['ff_opt_time']
     df_ot['opt_time2'] = df2['ff_opt_time']
     plot(df_ot, "bp_opt_time")
 
     df_op = pd.DataFrame(columns=['count_opt1' , 'count_opt2'])
     df_op['count_opt1'] = df1['ff_count_opt']
     df_op['count_opt2'] = df2['ff_count_opt']
     plot(df_op, "bp_count_opt_perm")    
 
 evaluate2(df1, df2)

Here is another executable example. I even used other variable names.

import pandas as pd 

d1 = {'ff_opt_time': [10, 20, 11, 5, 15 , 13, 19, 25  ], 'ff_count_opt': [30, 40, 45, 29, 35,38,32,41]}
df1 = pd.DataFrame(data=d1)
d2 = {'ff_opt_time': [1, 2, 1, 5, 1 , 1, 4, 5  ], 'ff_count_opt': [3, 4, 4, 9, 5,3, 2,4]}
df2 = pd.DataFrame(data=d2)

def evaluate2(df1, df2):

    df_ot = pd.DataFrame(columns=['opt_time1' , 'opt_time2'])
    df_ot['opt_time1'] = df1['ff_opt_time']
    df_ot['opt_time2'] = df2['ff_opt_time']
    boxplot1 = df_ot.boxplot(rot=45,fontsize=5)
    fig1 = boxplot1.get_figure()
    fig1.savefig( "bp_opt_time.pdf")

    df_op = pd.DataFrame(columns=['count_opt1' , 'count_opt2'])
    df_op['count_opt1'] = df1['ff_count_opt']
    df_op['count_opt2'] = df2['ff_count_opt']
    boxplot2 = df_op.boxplot(rot=45,fontsize=5)
    fig2 = boxplot2.get_figure()
    fig2.savefig( "bp_count_opt_perm.pdf")

evaluate2(df1, df2)
2 Answers

I can see from your code that boxplots: boxplot1 & boxplot2 are in the same graph. What you need to do is instruct that there is going to be two plots.

This can be achieved either by

  1. Create two sub plots using pyplot in matplotlib, this code does the trick fig1, ax1 = plt.subplots() with ax1 specifying boxplot to put in that axes and fig2 specifying boxplot figure
  2. Dissolve evaluate2 function and execute the boxplot separately in different cell in the jupyter notebook

Solution 1 : Two subplots using pyplot

import pandas as pd 
import matplotlib.pyplot as plt

d1 = {'ff_opt_time': [10, 20, 11, 5, 15 , 13, 19, 25  ], 'ff_count_opt': [30, 40, 45, 29, 35,38,32,41]}
df1 = pd.DataFrame(data=d1)
d2 = {'ff_opt_time': [1, 2, 1, 5, 1 , 1, 4, 5  ], 'ff_count_opt': [3, 4, 4, 9, 5,3, 2,4]}
df2 = pd.DataFrame(data=d2)

def evaluate2(df1, df2):
    df_ot = pd.DataFrame(columns=['opt_time1' , 'opt_time2'])
    df_ot['opt_time1'] = df1['ff_opt_time']
    df_ot['opt_time2'] = df2['ff_opt_time']
    fig1, ax1 = plt.subplots() 
    boxplot1 = df_ot.boxplot(rot=45,fontsize=5)
    ax1=boxplot1
    fig1 = boxplot1.get_figure()
    fig1.savefig( "bp_opt_time.pdf")

    df_op = pd.DataFrame(columns=['count_opt1' , 'count_opt2'])
    df_op['count_opt1'] = df1['ff_count_opt']
    df_op['count_opt2'] = df2['ff_count_opt']
    fig2, ax2 = plt.subplots()
    boxplot2 = df_op.boxplot(rot=45,fontsize=5)
    fig2 = boxplot2.get_figure()
    ax2=boxplot2
    fig2.savefig( "bp_count_opt_perm.pdf")
    plt.show()
evaluate2(df1, df2)

Solution 2: Executing boxplot in different cell

enter image description here

Update based on comments : clearing plots

Two ways you can clear the plot,

  • plot itself using clf() matplotlib.pyplot.clf() function to clear the current Figure’s state without closing it

  • clear axes using cla() matplotlib.pyplot.cla() function clears the current Axes state without closing the Axes.

Simply call plt.clf() function after calling fig.save

Read this documentation on how to clear a plot in Python using matplotlib

Just grab the code from Archana David and put it in your plot function: the goal is to call "fig, ax = plt.subplots()" to create a new graph.

import pandas as pd
import matplotlib.pyplot as plt
d1 = {'ff_opt_time': [10, 20, 11, 5, 15, 13, 19, 25],
    'ff_count_opt': [30, 40, 45, 29, 35, 38, 32, 41]}
df1 = pd.DataFrame(data=d1)
d2 = {'ff_opt_time': [1, 2, 1, 5, 1, 1, 4, 5],
    'ff_count_opt': [3, 4, 4, 9, 5, 3, 2, 4]}
df2 = pd.DataFrame(data=d2)
def evaluate2(df1, df2):
    def plot(df, output):
    fig, ax = plt.subplots()
    boxplot = df.boxplot(rot=45, fontsize=5)
    ax = boxplot
    fig = boxplot.get_figure()
    fig.savefig(output + ".pdf")

    df_ot = pd.DataFrame(columns=['opt_time1', 'opt_time2'])
    df_ot['opt_time1'] = df1['ff_opt_time']
    df_ot['opt_time2'] = df2['ff_opt_time']
    plot(df_ot, "bp_opt_time")

    df_op = pd.DataFrame(columns=['count_opt1' , 'count_opt2'])
    df_op['count_opt1'] = df1['ff_count_opt']
    df_op['count_opt2'] = df2['ff_count_opt']
    plot(df_op, "bp_count_opt_perm")    

evaluate2(df1, df2)
Related