How can I fix the facet (subplot) spacing for plotnine?

148 views Asked by At

Can someone help me determine why these images are coming out different from one another?

I am trying to re-generate a plot I made with plotnine. Unfortunately, running the same code seems to generate a different output. Here's the original output I was getting:

enter image description here

Here is the new output I am getting:

enter image description here

But I have not changed the code at all.

Here is the code:

from dfply import select, X
from matplotlib.font_manager import FontProperties
from mizani.breaks import log_breaks, mpl_breaks
from mizani.formatters import currency_format, custom_format, mpl_format,scientific_format
from mizani.transforms import log10_trans, identity_trans
from pandas import DataFrame, read_csv
from pathlib import Path
from plotnine import (
        aes, 
        element_blank, 
        element_line, 
        element_rect, 
        element_text, 
        facet_wrap, 
        geom_blank, 
        geom_line,  
        geom_point, 
        geom_vline, 
        ggplot, 
        labeller, 
        scale_x_continuous, 
        scale_y_continuous, 
        scale_y_log10, 
        theme)
from sys import path
from time import asctime, localtime, time

module_path = Path(__file__).resolve()
analysis_folder = module_path.parent
scripts_folder = analysis_folder.parent
operations_folder = str(scripts_folder) + '/operations'
project_folder = scripts_folder.parent
output_folder = str(project_folder) + '/output_analysis'
path.insert(0, str(operations_folder))
path.insert(0, str(scripts_folder))

from fixed_precision import fixed_precision as fixed_precision
from label_title import label_title as label_title
from revised_phase1_y_breaks import revised_phase1_y_breaks as revised_phase1_y_breaks
from revised_phase1_y_format import revised_phase1_y_format as revised_phase1_y_format

font_path = str(project_folder) + '/resources/fonts/Arial-Unicode-Regular.ttf'             
plot_title_properties = FontProperties(fname=font_path, size=12)
axis_title_properties = FontProperties(fname=font_path, size=11)
legend_title_properties = FontProperties(fname=font_path, size=11)
strip_text_properties = FontProperties(fname=font_path, size=11)
text_properties = FontProperties(fname=font_path, size=10)

phase1_dataframe = read_csv(
        str(output_folder) 
        + '/phase1_dataframe.csv') 


def create_phase1_plot():

        """
        Create the Phase 1 plot.

        :return: 'Date, time, and year: date_time_year
                Module: module_path
                Saved image: phase1_plot_location'
        :rtype: str
        """
        
        phase1_dataframe_combined = phase1_dataframe >> select (
                X.series, 
                X.trait, 
                X.time, 
                X.ancestor_seed,  
                X.ancestor_value, 
                X.ancestor_value_log10, 
                X.evolved_population_average_value, 
                X.evolved_population_average_value_log10)
        
        # Use ancestor data to plot ancestor values.
        fitness_ancestor_value =  (
                phase1_dataframe_combined.query(
                        "trait == 'fitness'")
                        # ['ancestor_value_log10']
                        ['ancestor_value']
                        .mean())
        genome_length_ancestor_value =  (
                phase1_dataframe_combined.query(
                        "trait == 'genome_length'")
                        # ['ancestor_value_log10']
                        ['ancestor_value']
                        .mean())
        trait_names = ["fitness", "genome_length",] 
        value = list([fitness_ancestor_value, genome_length_ancestor_value])
        ancestor_values = {'trait': trait_names, 'ancestor_value': value}  
        ancestor_data = DataFrame(ancestor_values) 

        # Generate fake data for framing.
        trait_names = ["fitness", "fitness", "genome_length", "genome_length"] 
        # trait_names = ["fitness", "fitness"] 
        value = [0.001, 10000000000, 70, 130]
        # value = [-0.0000000001, 10000000000]
        frame_nums = {'trait': trait_names, 'value': value}  
        frame_data = DataFrame(frame_nums) 
        
        phase1_plot = (
                ggplot(
                        data=phase1_dataframe_combined, 
                        mapping=aes(
                                x='time',
                                y='evolved_population_average_value', 
                                color= 'factor(ancestor_seed)', 
                                group= 'series'))
                + geom_line(size= .5)
                + geom_vline(xintercept=20000)
                + geom_vline(xintercept=100000)
                + geom_vline(xintercept=500000)

                + geom_point(
                        data= ancestor_data, 
                        mapping=aes(
                                x=0, 
                                y='ancestor_value'
                                ), 
                        shape= '*', 
                        size= 4, 
                        inherit_aes= False)
                + geom_blank(
                        data=frame_data, 
                        mapping=aes(y='value'), 
                        inherit_aes=False)
                + facet_wrap(
                        '~ trait', 
                        nrow=2, 
                        scales='free_y', 
                        labeller= labeller(trait=label_title))
                + scale_x_continuous(
                        name='Time (updates)', 
                        labels = currency_format(
                                prefix='', 
                                suffix='', 
                                digits=0, 
                                big_mark=','))
                + scale_y_log10(name='Average value',
                                breaks=revised_phase1_y_breaks,
                                labels=revised_phase1_y_format
                                )
                + theme(
                        figure_size=(5.2, 4.375),
                        legend_title_align= 'center',
                        text=element_text(fontproperties=text_properties),
                        title=element_text(
                                margin= {'b': 20}, 
                                fontproperties=plot_title_properties),
                        legend_position= 'none', 
                        plot_background=element_rect(fill='white'),
                        axis_text_x=element_text(
                                margin={'t':6}, 
                                color='black', 
                                size=8, 
                                fontproperties=text_properties),
                        axis_text_y=element_text(
                                margin={'r':6}, 
                                color='black', 
                                size=8, 
                                fontproperties=text_properties),
                        axis_title_x=element_text(
                                margin= {'t': 12}, 
                                fontproperties=axis_title_properties), 
                        axis_title_y=element_text(
                                margin= {'r': 18}, 
                                fontproperties=axis_title_properties),
                        axis_ticks_major_x=element_blank(),
                        axis_ticks_major_y=element_blank(),
                        rect=element_rect(
                                color='white', 
                                size=3, 
                                fill='white'),
                        panel_grid_major_y=element_line(
                                linetype='solid', 
                                color='gray', 
                                size=.5),
                        strip_text_x = element_text(
                                fontproperties=strip_text_properties),
                        panel_spacing = .3)) 

        phase1_plot_name= 'revised_phase1_2.pdf'
        phase1_plot.save(
                filename = phase1_plot_name, 
                path = (
                        output_folder 
                        + '/masked/phase1_plot'))

        date_time_year = asctime(localtime(time()))       
        
        return (
                '\n\n'
                'Date, time, and year: %s \n' 
                'Module: %s \n'
                'Saved image: %s' 
                % (
                date_time_year, 
                module_path, (
                        output_folder 
                        + '/masked/phase1_plot/' 
                        + phase1_plot_name)))

if __name__ == '__main__':
   print(create_phase1_plot())
1

There are 1 answers

0
has2k1 On

You do not need theme(panel_spacing=*) unless you want wider spacing.

Your first result is from earlier version (<0.12.0) of plotnine. plotnine==0.12.0 got a layout manager so your axis text will not overlap content from other panels.