How to render seaborn objects repeatedly? - python-3.x
The version of python I am using is 3.7. I tried it both in Spyder and JupyterNotebook
I used a sns.dataset as an example.
As I run the following code, the figure will be automatically rendered in IPython console without using plt.show() which is different from some instructions in previous posts.
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
df = sns.load_dataset('iris')
g = sns.pairplot(df, hue = 'species', height = 2.5)
However, I want to repeatedly show the seaborn object. How can I render g?
I've tried
plt.show(g)
g.show()
etc...
but none of them works. I do not want that everytime I call a figure, I have to re-plot it.
As long as you put the previously created figure object as the last line of new cells, this figure will return with whatever new additional elements, see cell 4 below:
In your case if g = ... is in your 1st cell, add an f = plt.gcf() to get the Figure object as here.
Related
Bokeh plot line not updating after checking CheckboxGroup in server mode (python callback)
I have just initiated myself to Bokeh library and I would like to add interactivity in my dashboard. To do so, I want to use CheckboxGroup widget in order to select which one of a pandas DataFrame column to plot. I have followed tutorials but I must have misunderstood the use of ColumnDataSource as I cannot make a simple example work... I am aware of previous questions on the matter, and one that seems relevant on the StackOverflow forum is the latter : Bokeh not updating plot line update from CheckboxGroup Sadly I did not succeed in reproducing the right behavior. I have tried to reproduce an example following the same updating structure presented in Bokeh Server plot not updating as wanted, also it keeps shifting and axis information vanishes by #bigreddot without success. import numpy as np import pandas as pd from bokeh.models import ColumnDataSource from bokeh.plotting import figure from bokeh.palettes import Spectral from bokeh.layouts import row from bokeh.models.widgets import CheckboxGroup from bokeh.io import curdoc # UPDATE FUNCTION ------------------------------------------------ # make update function def update(attr, old, new): feature_selected_test = [feature_checkbox.labels[i] for i in feature_checkbox.active] # add index to plot feature_selected_test.insert(0, 'index') # create new DataFrame new_df = dummy_df.filter(feature_selected_test) plot_src.data = ColumnDataSource.from_df(data=new_df) # CREATE DATA SOURCE ------------------------------------------------ # create dummy data for debugging purpose index = list(range(0, 890)) index.extend(list(range(2376, 3618))) feature_1 = np.random.rand(len(index)) feature_2 = np.random.rand(len(index)) feature_3 = np.random.rand(len(index)) feature_4 = np.random.rand(len(index)) dummy_df = pd.DataFrame(dict(index=index, feature_1=feature_1, feature_2=feature_2, feature_3=feature_3,feature_4=feature_4)) # CREATE CONTROL ------------------------------------------------------ # list available data to plot available_feature = list(dummy_df.columns[1:]) # initialize control feature_checkbox = CheckboxGroup(labels=available_feature, active=[0, 1], name='checkbox') feature_checkbox.on_change('active', update) # INITIALIZE DASHBOARD --------------------------------------------------- # initialize ColumnDataSource object plot_src = ColumnDataSource(dummy_df) # create figure line_fig = figure() feature_selected = [feature_checkbox.labels[i] for i in feature_checkbox.active] # feature_selected = ['feature_1', 'feature_2', 'feature_3', 'feature_4'] for index_int, col_name_str in enumerate(feature_selected): line_fig.line(x='index', y=col_name_str, line_width=2, color=Spectral[11][index_int % 11], source=plot_src) curdoc().add_root(row(feature_checkbox, line_fig)) The program should work with a copy/paste... well without interactivity... Would someone please help me ? Thanks a lot in advance.
You are only adding glyphs for the initial subset of selected features: for index_int, col_name_str in enumerate(feature_selected): line_fig.line(x='index', y=col_name_str, line_width=2, color=Spectral[11][index_int % 11], source=plot_src) So that is all that is ever going to show. Adding new columns to the CDS does not automatically make anything in particular happen, it's just extra data that is available for glyphs or hover tools to potentially use. To actually show it, there have to be glyphs configured to display those columns. You could do that, add and remove glyphs dynamically, but it would be far simpler to just add everything once up front, and use the checkbox to toggle only the visibility. There is an example of just this in the repo: https://github.com/bokeh/bokeh/blob/master/examples/app/line_on_off.py That example passes the data as literals the the glyph function but you could put all the data in CDS up front, too.
Creating a structured grid of subplots with Seaborn FacetGrid
My attempt to use FacetGrid in Seaborn does not produces the expected results. Moreover, I would like to control the white space in the grid. My data and code is the following: toy.to_json() '{"has_cus_id_but_not_acc_id":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":1,"19":0,"20":0,"21":0,"22":1,"23":0,"24":0,"25":1,"26":0,"27":1,"28":0,"29":1,"30":0,"31":1,"32":0,"33":1,"34":0,"35":1,"36":0,"37":1,"38":0,"39":0,"40":1,"41":1,"42":0,"43":1,"44":0,"45":1,"46":0,"47":1,"48":0,"49":1,"50":0,"51":1,"52":0,"53":1,"54":0,"55":1,"56":0,"57":1,"58":0,"59":1,"60":0,"61":1,"62":0,"63":1,"64":0,"65":1,"66":0,"67":1,"68":0,"69":1,"70":0,"71":1,"72":0,"73":1,"74":0,"75":1,"76":0,"77":0,"78":1,"79":0,"80":1,"81":0,"82":0,"83":1,"84":0,"85":1},"reg_year":{"0":2014.0,"1":2014.0,"2":2014.0,"3":2014.0,"4":2014.0,"5":2014.0,"6":2014.0,"7":2014.0,"8":2015.0,"9":2015.0,"10":2015.0,"11":2015.0,"12":2015.0,"13":2015.0,"14":2015.0,"15":2015.0,"16":2015.0,"17":2016.0,"18":2016.0,"19":2016.0,"20":2016.0,"21":2016.0,"22":2016.0,"23":2016.0,"24":2016.0,"25":2016.0,"26":2016.0,"27":2016.0,"28":2016.0,"29":2016.0,"30":2016.0,"31":2016.0,"32":2016.0,"33":2016.0,"34":2016.0,"35":2016.0,"36":2016.0,"37":2016.0,"38":2017.0,"39":2017.0,"40":2017.0,"41":2017.0,"42":2017.0,"43":2017.0,"44":2017.0,"45":2017.0,"46":2017.0,"47":2017.0,"48":2017.0,"49":2017.0,"50":2017.0,"51":2017.0,"52":2017.0,"53":2017.0,"54":2017.0,"55":2017.0,"56":2017.0,"57":2017.0,"58":2017.0,"59":2017.0,"60":2018.0,"61":2018.0,"62":2018.0,"63":2018.0,"64":2018.0,"65":2018.0,"66":2018.0,"67":2018.0,"68":2018.0,"69":2018.0,"70":2018.0,"71":2018.0,"72":2018.0,"73":2018.0,"74":2018.0,"75":2018.0,"76":2018.0,"77":2018.0,"78":2018.0,"79":2018.0,"80":2018.0,"81":2018.0,"82":2019.0,"83":2019.0,"84":2019.0,"85":2019.0},"reg_month":{"0":3.0,"1":5.0,"2":6.0,"3":7.0,"4":9.0,"5":10.0,"6":11.0,"7":12.0,"8":1.0,"9":3.0,"10":5.0,"11":6.0,"12":7.0,"13":8.0,"14":9.0,"15":11.0,"16":12.0,"17":1.0,"18":1.0,"19":2.0,"20":3.0,"21":4.0,"22":4.0,"23":5.0,"24":6.0,"25":6.0,"26":7.0,"27":7.0,"28":8.0,"29":8.0,"30":9.0,"31":9.0,"32":10.0,"33":10.0,"34":11.0,"35":11.0,"36":12.0,"37":12.0,"38":1.0,"39":2.0,"40":2.0,"41":3.0,"42":4.0,"43":4.0,"44":5.0,"45":5.0,"46":6.0,"47":6.0,"48":7.0,"49":7.0,"50":8.0,"51":8.0,"52":9.0,"53":9.0,"54":10.0,"55":10.0,"56":11.0,"57":11.0,"58":12.0,"59":12.0,"60":1.0,"61":1.0,"62":2.0,"63":2.0,"64":3.0,"65":3.0,"66":4.0,"67":4.0,"68":5.0,"69":5.0,"70":6.0,"71":6.0,"72":7.0,"73":7.0,"74":8.0,"75":8.0,"76":9.0,"77":10.0,"78":10.0,"79":11.0,"80":11.0,"81":12.0,"82":1.0,"83":1.0,"84":2.0,"85":2.0},"Total_Revenue":{"0":35852.02,"1":2623.97,"2":3526.67,"3":21466.71,"4":72784.1200000003,"5":103921.2899999999,"6":10852.87,"7":16522.07,"8":7443.76,"9":68962.1600000002,"10":10956.38,"11":193856.8799999985,"12":110766.6099999997,"13":123861.8599999987,"14":2722.34,"15":303488.6900000007,"16":6876.58,"17":17729.5,"18":4687.93,"19":26914.06,"20":2228.12,"21":15708.93,"22":859.58,"23":19164.89,"24":163164.4799999995,"25":33180.7300000001,"26":10033.01,"27":1114.48,"28":462613.2900000042,"29":9822.95,"30":70901.4400000003,"31":22370.29,"32":46711.8900000002,"33":2335.02,"34":7259.28,"35":11.83,"36":13590.51,"37":7677.77,"38":282.01,"39":358522.7900000003,"40":5844.0,"41":7027.28,"42":1908.71,"43":4032.35,"44":11072.6,"45":3973.15,"46":30706.23,"47":2644.13,"48":23831.75,"49":670.12,"50":6949.54,"51":4687.7,"52":9672.69,"53":7333.01,"54":12814.33,"55":689.39,"56":6962.86,"57":2283.16,"58":1259.5,"59":224.84,"60":12812.12,"61":247.68,"62":25452.65,"63":1245.02,"64":24211.36,"65":5255.25,"66":28402.76,"67":9148.55,"68":14822.61,"69":345.37,"70":12408.13,"71":989.93,"72":10601.33,"73":730.32,"74":169020.5000000001,"75":697.54,"76":3862038.6799997138,"77":6148750.9899984254,"78":194.06,"79":2379382.4500000761,"80":1174.11,"81":1729567.9000000793,"82":889650.029999995,"83":95.8,"84":415996.6999999974,"85":654.78}}' g = sns.FacetGrid(toy, col='has_cus_id_but_not_acc_id', hue='reg_year') g.map(sns.barplot, 'reg_month', 'Total_Revenue') g.add_legend(); If I use bar in pyplot I get this: g = sns.FacetGrid(toy, col='has_cus_id_but_not_acc_id', hue='reg_year') g.map(plt.bar, 'reg_month', 'Total_Revenue') g.add_legend(); Again, I would like to be able to define the white space of the grid. In addition I would not like to have the bars stacked one over the other but rather one next to the other.
Some values of the year 2018 are really large compared to the any of the values where has_cus_id_but_not_acc_id is 1. Hence the right plot is almost empty. It might make sense to use a logarithmic scale. Now you have 6 years, so each month would need to show 6 bars next to each other. That will make bars pretty small and does not let the chart be easily readable. Still it's possible. The following does not use seaborn, but pandas and matplotlib: import matplotlib.pyplot as plt import pandas as pd toy = '{"has_cus_id_but_not_acc_id":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":1,"19":0,"20":0,"21":0,"22":1,"23":0,"24":0,"25":1,"26":0,"27":1,"28":0,"29":1,"30":0,"31":1,"32":0,"33":1,"34":0,"35":1,"36":0,"37":1,"38":0,"39":0,"40":1,"41":1,"42":0,"43":1,"44":0,"45":1,"46":0,"47":1,"48":0,"49":1,"50":0,"51":1,"52":0,"53":1,"54":0,"55":1,"56":0,"57":1,"58":0,"59":1,"60":0,"61":1,"62":0,"63":1,"64":0,"65":1,"66":0,"67":1,"68":0,"69":1,"70":0,"71":1,"72":0,"73":1,"74":0,"75":1,"76":0,"77":0,"78":1,"79":0,"80":1,"81":0,"82":0,"83":1,"84":0,"85":1},"reg_year":{"0":2014.0,"1":2014.0,"2":2014.0,"3":2014.0,"4":2014.0,"5":2014.0,"6":2014.0,"7":2014.0,"8":2015.0,"9":2015.0,"10":2015.0,"11":2015.0,"12":2015.0,"13":2015.0,"14":2015.0,"15":2015.0,"16":2015.0,"17":2016.0,"18":2016.0,"19":2016.0,"20":2016.0,"21":2016.0,"22":2016.0,"23":2016.0,"24":2016.0,"25":2016.0,"26":2016.0,"27":2016.0,"28":2016.0,"29":2016.0,"30":2016.0,"31":2016.0,"32":2016.0,"33":2016.0,"34":2016.0,"35":2016.0,"36":2016.0,"37":2016.0,"38":2017.0,"39":2017.0,"40":2017.0,"41":2017.0,"42":2017.0,"43":2017.0,"44":2017.0,"45":2017.0,"46":2017.0,"47":2017.0,"48":2017.0,"49":2017.0,"50":2017.0,"51":2017.0,"52":2017.0,"53":2017.0,"54":2017.0,"55":2017.0,"56":2017.0,"57":2017.0,"58":2017.0,"59":2017.0,"60":2018.0,"61":2018.0,"62":2018.0,"63":2018.0,"64":2018.0,"65":2018.0,"66":2018.0,"67":2018.0,"68":2018.0,"69":2018.0,"70":2018.0,"71":2018.0,"72":2018.0,"73":2018.0,"74":2018.0,"75":2018.0,"76":2018.0,"77":2018.0,"78":2018.0,"79":2018.0,"80":2018.0,"81":2018.0,"82":2019.0,"83":2019.0,"84":2019.0,"85":2019.0},"reg_month":{"0":3.0,"1":5.0,"2":6.0,"3":7.0,"4":9.0,"5":10.0,"6":11.0,"7":12.0,"8":1.0,"9":3.0,"10":5.0,"11":6.0,"12":7.0,"13":8.0,"14":9.0,"15":11.0,"16":12.0,"17":1.0,"18":1.0,"19":2.0,"20":3.0,"21":4.0,"22":4.0,"23":5.0,"24":6.0,"25":6.0,"26":7.0,"27":7.0,"28":8.0,"29":8.0,"30":9.0,"31":9.0,"32":10.0,"33":10.0,"34":11.0,"35":11.0,"36":12.0,"37":12.0,"38":1.0,"39":2.0,"40":2.0,"41":3.0,"42":4.0,"43":4.0,"44":5.0,"45":5.0,"46":6.0,"47":6.0,"48":7.0,"49":7.0,"50":8.0,"51":8.0,"52":9.0,"53":9.0,"54":10.0,"55":10.0,"56":11.0,"57":11.0,"58":12.0,"59":12.0,"60":1.0,"61":1.0,"62":2.0,"63":2.0,"64":3.0,"65":3.0,"66":4.0,"67":4.0,"68":5.0,"69":5.0,"70":6.0,"71":6.0,"72":7.0,"73":7.0,"74":8.0,"75":8.0,"76":9.0,"77":10.0,"78":10.0,"79":11.0,"80":11.0,"81":12.0,"82":1.0,"83":1.0,"84":2.0,"85":2.0},"Total_Revenue":{"0":35852.02,"1":2623.97,"2":3526.67,"3":21466.71,"4":72784.1200000003,"5":103921.2899999999,"6":10852.87,"7":16522.07,"8":7443.76,"9":68962.1600000002,"10":10956.38,"11":193856.8799999985,"12":110766.6099999997,"13":123861.8599999987,"14":2722.34,"15":303488.6900000007,"16":6876.58,"17":17729.5,"18":4687.93,"19":26914.06,"20":2228.12,"21":15708.93,"22":859.58,"23":19164.89,"24":163164.4799999995,"25":33180.7300000001,"26":10033.01,"27":1114.48,"28":462613.2900000042,"29":9822.95,"30":70901.4400000003,"31":22370.29,"32":46711.8900000002,"33":2335.02,"34":7259.28,"35":11.83,"36":13590.51,"37":7677.77,"38":282.01,"39":358522.7900000003,"40":5844.0,"41":7027.28,"42":1908.71,"43":4032.35,"44":11072.6,"45":3973.15,"46":30706.23,"47":2644.13,"48":23831.75,"49":670.12,"50":6949.54,"51":4687.7,"52":9672.69,"53":7333.01,"54":12814.33,"55":689.39,"56":6962.86,"57":2283.16,"58":1259.5,"59":224.84,"60":12812.12,"61":247.68,"62":25452.65,"63":1245.02,"64":24211.36,"65":5255.25,"66":28402.76,"67":9148.55,"68":14822.61,"69":345.37,"70":12408.13,"71":989.93,"72":10601.33,"73":730.32,"74":169020.5000000001,"75":697.54,"76":3862038.6799997138,"77":6148750.9899984254,"78":194.06,"79":2379382.4500000761,"80":1174.11,"81":1729567.9000000793,"82":889650.029999995,"83":95.8,"84":415996.6999999974,"85":654.78}}' df = pd.read_json(toy) df['reg_year'].astype(int) u = df["has_cus_id_but_not_acc_id"].unique() y = df['reg_year'].unique() fig, axes = plt.subplots(1,len(u), sharey=True) axes[0].set_yscale("log") for ax, (n, grp) in zip(axes.flat, df.groupby("has_cus_id_but_not_acc_id")): piv = grp.pivot('reg_month', 'reg_year', 'Total_Revenue') empty = pd.DataFrame(index=range(1,12), columns=y) empty.combine_first(piv).plot.bar(ax=ax, width=0.8, legend=False) axes[1].legend() plt.show()
Bokeh ValueError: expected an element of either Seq(String)
I'm trying to build a simple bar chart via bokeh but struggling for it to recognize the x-axis and keep getting a ValueError... I think it needs to be in string format but for some reason whatever I try it just won't work. Please note, the column that contains the Years (as floats by the looks of it) is called RegionName, if it seems confusing. Please see my code below, any suggestions? import pandas as pd from bokeh.plotting import figure, output_file, show from bokeh.models import ColumnDataSource from bokeh.models.tools import HoverTool import os from bokeh.palettes import Spectral5 from bokeh.transform import factor_cmap os.chdir("C:/Users/Vladimir.Tikhnenko/Python/Land Reg") # Pivot data def pivot2(infile="Land Registry.csv", outfile="SalesVolume.csv"): df=pd.read_csv(infile) table=pd.pivot_table(df,index= ["RegionName"],columns="Year",values="SalesVolume",aggfunc=sum) table.to_csv(outfile) return table pivot2() # Transpose data df=pd.read_csv("SalesVolume.csv") df=df.drop(df.columns[1:28],1) df=pd.read_csv("SalesVolume.csv", index_col=0, header=None).T df.to_csv("C:\\Users\Vladimir.Tikhnenko\Python\Land Reg\SalesVolume.csv",index=None) df=pd.read_csv("SalesVolume.csv") source = ColumnDataSource(df) years = source.data['RegionName'].tolist() p = figure(x_range=['RegionName']) color_map = factor_cmap(field_name='RegionName',palette=Spectral5, factors=years) p.vbar(x='RegionName', top='Southwark', source=source, width=1, color=color_map) p.title.text ='Transactions' p.xaxis.axis_label = 'Years' p.yaxis.axis_label = 'Number of Sales' show(p) the error message is ValueError: expected an element of either Seq(String), Seq(Tuple(String, String)) or Seq(Tuple(String, String, String)), got [1968.0, 1969.0, 1970.0, 1971.0, 1972.0, 1973.0, 1974.0, 1975.0, 1976.0, 1977.0, 1978.0, 1979.0, 1980.0, 1981.0, 1982.0, 1983.0, 1984.0, 1985.0, 1986.0, 1987.0, 1988.0, 1989.0, 1990.0, 1991.0, 1992.0, 1993.0, 1994.0, 1995.0, 1996.0, 1997.0, 1998.0, 1999.0, 2000.0, 2001.0, 2002.0, 2003.0, 2004.0, 2005.0, 2006.0, 2007.0, 2008.0, 2009.0, 2010.0, 2011.0, 2012.0, 2013.0, 2014.0, 2015.0, 2016.0, 2017.0, 2018.0]
Categorical factors must only be strings (or sequences of strings for nested factors), so factor_cmap only accepts lists of those things. You passed it a list a numbers, which causes the error shown. To use use the years as categorical factors, you need to convert them to strings as suggested, and use those string values to initialize x_range, and for the coordinates to vbar. Alternatively, if you want to use numerical values for the years, but just want to have fixed, controlled tick locations, do this: p = figure() # don't pass x_range p.xaxis.ticker = years And then also use linear_cmap to map the numerical values (instead of factor_cmap)
How to make an altair plot within an IF statement?
The situation seems to be quite simple: I am working in a Jupyter Lab file with several Altair plots, which eventually make the file too large to run and to save. Since I don't need to see these plots every single time, I figured I could avoid this by specifying something like plotAltair = True at the beginning of the script and then nesting each Altair plot in if statements. As simple as this may sound, for some reason it doesn't appear to work. Am I missing out on something obvious? [edit: turns out I was] For instance: import altair as alt import os import pandas as pd import numpy as np lengths = np.random.randint(0,100,200) lengths_list = lengths.tolist() labels = [str(i) for i in lengths_list] peak_lengths = pd.DataFrame.from_dict({'coords': labels, 'lengths': lengths_list}, orient='columns') What works: alt.Chart(peak_lengths).mark_bar().encode( x = alt.X('lengths:Q', bin=True), y='count(*):Q' ) What doesn't work: plotAltair = True if plotAltair: alt.Chart(peak_lengths).mark_bar().encode( x = alt.X('lengths:Q', bin=True), y='count(*):Q' ) ** Obs.: I have already attempted to use alt.data_transformers.enable('json') as a way of reducing file size and it is also not working, but let's please not focus on this but rather on the more simple question.
Short answer: use chart.display() Long answer: Jupyter notebooks in general will only display things if you tell them to. For example, this code will not result in any output: if x: x + 1 You are telling the notebook to evaluate x + 1, but not to do anything with it. What you need to do is tell the notebook to print the result, either implicitly by putting it as the last line in the main block of the cell, or explicitly by asking for it to be printed when the statement appears anywhere else: if x: print(x + 1) It is similar for Altair charts, which are just normal Python objects. If you put the chart at the end of the cell, you are implicitly asking for the result to be displayed, and Jupyter will display it as it will any variable. If you want it to be displayed from any other location in the cell, you need to explicitly ask that it be displayed using the IPython.display.display() function: from IPython.display import display if plotChart: chart = alt.Chart(data).mark_point().encode(x='x', y='y') display(chart) Because this extra import is a bit verbose, Altair provides a .display() method as a convenience function to do the same thing: if plotChart: chart = alt.Chart(data).mark_point().encode(x='x', y='y') chart.display() Note that calling .display() on multiple charts is the way that you can display multiple charts in a single cell.
Need help in creating a function to plot a Matplotlib GridSpec
I have a dataset with 80 variables. I am interested in creating a function that will automate the creation of a 20 X 4 GridSpec in Matplotlib. Each subplot would either contain a histogram or a barplot for each of the 80 variables in the data. As a first step, I successfully created two functions (I call them 'counts' and 'histogram') that contain the layout of the plot that I want. Both of them work when tested on individual variables. As a next step, I attempted to create a function that would take the column names, loop through a conditional to test whether the data type is an object or otherwise and call the right function based on the datatype as a new subplot. Here is the code that I have so far: Creates list of coordinates we will need for subplot specification: A = np.arange(21) B = np.arange(4) coords = [] for i in A: for j in B: coords.append([A[i], B[j]]) #Create the gridspec and layout the figure import matplotlib.gridspec as gridspec fig = plt.figure(figsize=(12,6)) gs = gridspec.GridSpec(2,4) #Function that relies on what we've done above: def grid(cols=['MSZoning', 'LotFrontage', 'LotArea', 'Street', 'Alley']): for i in cols: for vals in coords: if str(train[i].dtype) == 'object': plt.subplot('gs'+str(vals)) counts(cols) else: plt.subplot('gs'+str(vals)) histogram(cols) When attempted, this code returns an error: ValueError: Single argument to subplot must be a 3-digit integer For purposes of helping you visualize, what I am hoping to achieve, I attach the screen shot below, which was produced by the line by line coding (with my created helper functions) I am trying to avoid: Can anyone help me figure out where I am going wrong? I would appreciate any advice. Thank you!
The line plt.subplot('gs'+str(vals)) cannot work; which is also what the error tells you. As can be seen from the matplotlib GridSpec tutorial, it needs to be ax = plt.subplot(gs[0, 0]) So in your case you may use the values from the list as ax = plt.subplot(gs[vals[0], vals[1]]) Mind that you also need to make sure that the coords list must have the n*m elements, if the gridspec is defined as gs = gridspec.GridSpec(n,m).