Python Forum
Nested for loops - help with iterating a variable outside of the main loop
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Nested for loops - help with iterating a variable outside of the main loop
#1
Hi all,

First of all there isn't 27 attachments to this question there are 5.
I have made the question more concise so please do read again.

I am working on my first python project and this is my first time posting in a forum.
I am trying to write a function which plots individual country's inflation data against the years since inflation data was collected for said country (in years) in separate subplots within the same figure.
The issue I am having is either being able to plot the last country's inflation data on all subplots OR all countries inflation data on all subplots.
I am working on a Jupyter Notebook on the Anaconda platform.

QUESTION: How can I change this function so as to plot the first country's inflation data on the first subplot, the second country's inflation data on the second subplot, and so on.
The below code (ATTEMPT 1) returns 4 subplots, each subplot contains the 4 countries inflation data.
ATTEMPT 1


# Subplots function with df_transposed dataframe ISSUE: returns subplots each plotting all selected country data.
# This function takes in two arguments: "df" the DataFrame, and "df_col_range" the range of country columns
# to plot.
# This function uses the dictionary "col_pos" to access columns.
# This code appears to plot p = 1-4, (1)Aruba, (2)Africa Eastern and Southern, (3)Afghanistan, (4)Africa Western 
# and Central.

def global_inf_subplots_func(df, col_range_index):
    # col_pos creates a dictionary so as to be access columns by position (column index)
    col_pos = {df_transposed.columns.get_loc(c): c for idx, c in enumerate(df_transposed.columns)}
    
    x = df_transposed['years']
    
    rows, cols = int(col_range_index/2), int(col_range_index/2)
    
    fig, ax = plt.subplots(rows, cols, figsize = (30, 30),
                       sharex='col', 
                       sharey='row')

    
    for row in range(rows):
        for col in range(cols):
   
            for p in col_pos:
                if p != 0 and p < col_range_index:
                    y = df_transposed.iloc[:, p]
                    ax[row, col].plot(x, y)
                
plt.show()
                
global_inf_subplots_func(df_transposed, 5)
Output:
   
QUESTION: The below attempt (attempt 2) has the same goal (to plot 4 subplots, each subplot containing different country's inflation data. Instead, all 4 subplots have the last country of the 4 selected plotted.
Attempt 2:



# Subplots function with df_transposed dataframe **** on each iteration, same y axis data is being plotted 
# I need the code to add the next iteration of the dataframes columns to be plotted on the next subplot, 
# then move onto the next

# This function takes in four arguments: "df" the DataFrame, and "df_col_range" the range of country columns
# to plot, "rows" the number of rows of subplots the figure needs to hold, "cols" the number of columns of 
# subplots the figure needs to hold.
# This function used the dictionary "col_pos" to access columns.

# This code appears to plot p = 4, (4) Africa Western and Central, ONLY - Explanation????: the first for loop,
# Iterates over p = 1 to 4 and therefore p = 4 is the last return, 
# Therefore p = 4 is used in y = df_transposed.iloc[:, p] and is used in the subsequent subplots????

def global_inf_subplots_func(df, col_range_index, rows, cols):
    
    # col_pos creates a dictionary so as to be access columns by position (column index)
    col_pos = {df_transposed.columns.get_loc(c): c for idx, c in enumerate(df_transposed.columns)}
    
    x = df_transposed['years']
    
    rows, cols = rows, cols
    
    fig, ax = plt.subplots(rows, cols, figsize = (30, 30),
                       sharex='col', 
                       sharey='row')
    
    for p in col_pos:
        if p != 0 and p < col_range_index:
            y = df_transposed.iloc[:, p]
            
        
    for row in range(rows):
        for col in range(cols):
            ax[row, col].plot(x, y)
              
plt.show()
                
global_inf_subplots_func(df_transposed, 5, 2, 2)
Output:
   
QUESTION: Why does this function plot ALL countries inflation data on each subplot, when only the 4 (as previous) were selected.
Attempt 3:


# Subplots function with df_transposed dataframe **** on each iteration, same y axis data is being plotted 
# I need the code to add the next iteration of the dataframes columns to be plotted on the next subplot, 
# then move onto the next

# This function takes in four arguments: "df" the DataFrame, and "df_col_range" the range of country columns
# to plot, "rows" the number of rows of subplots the figure needs to hold, "cols" the number of columns of 
# subplots the figure needs to hold.
# This function used the dictionary "col_pos" to access columns.

# This code appears to plot ALL countries, and therefore all columns
# (eventhough only 4 countries (4 columns) selected from col_pos)

def global_inf_subplots_func(df, col_range_index, rows, cols):
    
    # col_pos creates a dictionary so as to be access columns by position (column index)
    col_pos = {df_transposed.columns.get_loc(c): c for idx, c in enumerate(df_transposed.columns)}
    

    x = df_transposed['years']
    
    rows, cols = rows, cols
    
    fig, ax = plt.subplots(rows, cols, figsize = (30, 30),
                       sharex='col')

    for p in col_pos:
        if p != 0 and p > col_range_index:
            y = df_transposed.iloc[:,p]
            for row in range(rows):
                for col in range(cols):
                    ax[row, col].plot(x, y)

plt.show()
                
global_inf_subplots_func(df_transposed, 5, 2, 2)
Output:
   
Just for information.... I have also tried to achieve the same with a different approach:
Attempt 4:


def plot_global_inf_sub():
    for c in df_transposed['Aruba':'Zimbabwe']:
        n = len(df_transposed.columns) -1
        i = 0
        a = 1
        x = years
        fig, ax = plt.subplots(int(n/2), int(n/2))
        while i >= n:
                ax[i,(i-i)].plot(x, c)
                ax[i, a(i=+1)].plot(x, c)
                y = df_transposed[c]
                plt.plot(x, y)
                plt.show()
        
plot_global_inf_sub()
No output to the above, In[*] occurs.

Attempt 5:

def plot_global_inf_sub():
        n = len(df_transposed.columns)
        x = years
        p = 1
        i = 0
        for c in df_transposed.loc['Aruba':'Zimbabwe']:
            for p in range(n):
                for q in range(n): 
                    if i <= n:
                        m = p(ax(p), ax(q))
                        fig, m = plt.subplots(int(n/2), int(n/2))
                        a = 1
                        y = df_transposed[c]
                        ax[i,(i-i)].plot(x, y)
                        ax[i, a(i=+1)].plot(x, y)
                        plt.show()
        
plot_global_inf_sub()
Error:
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) /var/folders/7n/v1x237vx47z_7y3g2_63b64h0000gs/T/ipykernel_6003/2417806721.py in <module> 16 plt.show() 17 ---> 18 plot_global_inf_sub() /var/folders/7n/v1x237vx47z_7y3g2_63b64h0000gs/T/ipykernel_6003/2417806721.py in plot_global_inf_sub() 8 for q in range(n): 9 if i <= n: ---> 10 m = p(ax(p), ax(q)) 11 fig, m = plt.subplots(int(n/2), int(n/2)) 12 a = 1 TypeError: 'numpy.ndarray' object is not callable
Notes from script:
# This script attempts to code for a function "global_inf_subplots_func()" the aim of which is to plot multiple
# subplots. Each subplot should plot years 1960 - 2021 on the x axis, against subsequent countries inflation %
# on the y axis.
# The x axis data is from "x = df_transposed['years']", the years column from the transposed DataFrame:
# df_transposed.
# The y axis data is from the col _pos dictionary. This dictionary gives a number as a key and the respective
# countries inflation % data as a value.

# (Aim*) The overall aim of this function is to be able to plot years vs country (n) inflation data,
# each subsequent subplot containing the next countries inflation % data in the col_pos dictionary.

The DataFrame used in this code:

df_transposed
Output:
Country Name years Aruba Africa Eastern and Southern Afghanistan Africa Western and Central Angola Albania Andorra Arab World United Arab Emirates ... Virgin Islands (U.S.) Vietnam Vanuatu World Samoa Kosovo Yemen, Rep. South Africa Zambia Zimbabwe 1960 1960 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN 1.288859 NaN NaN 1961 1961 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN 2.102374 NaN NaN 1962 1962 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN 2.654867 NaN NaN 1.246285 NaN NaN 1963 1963 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN 0.689655 NaN NaN 1.337970 NaN NaN 1964 1964 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN 5.308219 NaN NaN 2.534973 NaN NaN ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 2017 2017 -1.028282 6.399343 4.975952 1.764635 29.843587 2.060598 NaN 1.966826 1.966826 ... NaN 3.520257 3.084526 2.192010 1.749897 1.488234 NaN 5.184247 6.577312 0.893962 2018 2018 3.626041 4.720811 0.626149 1.784050 19.628608 2.028060 NaN 2.458142 3.068634 ... NaN 3.539628 2.330964 2.438737 4.197459 1.053798 NaN 4.517165 7.494572 10.618866 2019 2019 4.257462 4.120246 2.302373 1.758565 17.081215 1.411091 NaN 1.091848 -1.931081 ... NaN 2.795824 2.762520 2.186902 0.982327 2.675992 NaN 4.120246 9.150316 255.304991 2020 2020 NaN 5.404815 NaN 2.492522 NaN 1.620887 NaN 1.777408 -2.079403 ... NaN 3.220934 5.329351 1.920968 -1.568912 0.198228 NaN 3.210036 15.732585 557.201817 2021 2021 NaN 7.240978 NaN 3.925603 NaN 2.041472 NaN 3.243460 NaN ... NaN 1.834716 2.343284 3.423629 3.133205 3.353691 NaN 4.611672 22.021234 98.546105

Attached Files

Thumbnail(s)
       
Reply
#2
Try posting your questions one at a time. I have no idea how to answer everything you've asked so far. I don't really understand what you are asking half the time.

Starting with you last edit. Python thinks ax[index] is indexing a value in a list or array and ax(index) is a function call.

This is where Python sees the error:
Error:
---> 10 m = p(ax(p), ax(q))
And this is what Python thinks the error is:
Error:
TypeError: 'numpy.ndarray' object is not callable
For indexing use [], not ().


In your first attempt at plotting you got an error because you called the plot function with an invalid argument.
This is where Python sees the error:
Error:
---> 11 ax[row, col].plot(x, y, color="green", fontsize=18, ha='center')
And this is what Python thinks the error is:
Error:
AttributeError: 'Line2D' object has no property 'fontsize'
If you look at the documentation you would see that it does't have a fontsize argument.

https://matplotlib.org/stable/api/_as_ge....plot.html

if you have additional questions please ask them as new posts to this thread. Do not edit your original post.
Reply
#3
(Aug-17-2022, 09:06 PM)deanhystad Wrote: Try posting your questions one at a time. I have no idea how to answer everything you've asked so far. I don't really understand what you are asking half the time.

Starting with you last edit. Python thinks ax[index] is indexing a value in a list or array and ax(index) is a function call.

This is where Python sees the error:
Error:
---> 10 m = p(ax(p), ax(q))
And this is what Python thinks the error is:
Error:
TypeError: 'numpy.ndarray' object is not callable
For indexing use [], not ().


In your first attempt at plotting you got an error because you called the plot function with an invalid argument.
This is where Python sees the error:
Error:
---> 11 ax[row, col].plot(x, y, color="green", fontsize=18, ha='center')
And this is what Python thinks the error is:
Error:
AttributeError: 'Line2D' object has no property 'fontsize'
If you look at the documentation you would see that it does't have a fontsize argument.

https://matplotlib.org/stable/api/_as_ge....plot.html

if you have additional questions please ask them as new posts to this thread. Do not edit your original post.

Thank you, firstly, I've made the question far more concise. I appreciate your advice on that. Hopefully my questions are clearer now.

Regarding your first point, I've change from () to []:
def plot_global_inf_sub():
        n = len(df_transposed.columns)
        x = years
        p = 1
        i = 0
        for c in df_transposed.loc['Aruba':'Zimbabwe']:
            for p in range(n):
                for q in range(n): 
                    if i <= n:
                        m = p(ax[p], ax[q])
                        fig, m = plt.subplots(int(n/2), int(n/2))
                        a = 1
                        y = df_transposed[c]
                        ax[i,(i-i)].plot(x, y)
                        ax[i, a(i=+1)].plot(x, y)
                        plt.show()
        
plot_global_inf_sub()
And now get the following error:
Error:
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) /var/folders/7n/v1x237vx47z_7y3g2_63b64h0000gs/T/ipykernel_6003/19824294.py in <module> 16 plt.show() 17 ---> 18 plot_global_inf_sub() /var/folders/7n/v1x237vx47z_7y3g2_63b64h0000gs/T/ipykernel_6003/19824294.py in plot_global_inf_sub() 8 for q in range(n): 9 if i <= n: ---> 10 m = p(ax[p], ax[q]) 11 fig, m = plt.subplots(int(n/2), int(n/2)) 12 a = 1 TypeError: 'int' object is not callable
It's good for me to read and understand your error/explanation reply, thank you.
Reply
#4
(Aug-17-2022, 09:06 PM)deanhystad Wrote: Try posting your questions one at a time. I have no idea how to answer everything you've asked so far. I don't really understand what you are asking half the time.

Starting with you last edit. Python thinks ax[index] is indexing a value in a list or array and ax(index) is a function call.

This is where Python sees the error:
Error:
---> 10 m = p(ax(p), ax(q))
And this is what Python thinks the error is:
Error:
TypeError: 'numpy.ndarray' object is not callable
For indexing use [], not ().


In your first attempt at plotting you got an error because you called the plot function with an invalid argument.
This is where Python sees the error:
Error:
---> 11 ax[row, col].plot(x, y, color="green", fontsize=18, ha='center')
And this is what Python thinks the error is:
Error:
AttributeError: 'Line2D' object has no property 'fontsize'
If you look at the documentation you would see that it does't have a fontsize argument.

https://matplotlib.org/stable/api/_as_ge....plot.html

if you have additional questions please ask them as new posts to this thread. Do not edit your original post.

Sorry I've done exactly what you've said not to do, ask new questions and edited the original post. If you can, can you briefly explain why so I can post better in the future. I don't want a bad reputation and annoy responders.
Thanks.
Reply
#5
It is best to focus a post on a single question. This makes it easier for other to reply. When you ask multiple questions in one post it becomes difficult to map responses to the questions. I know that I am less likely to respond to, or even read a long post.

It is ok to edit posts if you notice there is an error, but you should avoid changing the content of a post, especially if there are replies. Threads should read like a conversation. I don't want the first post to reference the third post.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Variable definitions inside loop / could be better? gugarciap 2 430 Jan-09-2024, 11:11 PM
Last Post: deanhystad
  How to create a variable only for use inside the scope of a while loop? Radical 10 1,683 Nov-07-2023, 09:49 AM
Last Post: buran
  reduce nested for-loops Phaze90 11 1,867 Mar-16-2023, 06:28 PM
Last Post: ndc85430
  Big O runtime nested for loop and append yarinsh 4 1,374 Dec-31-2022, 11:50 PM
Last Post: stevendaprano
  Nested for loops: Iterating over columns of a DataFrame to plot on subplots dm222 0 1,704 Aug-19-2022, 11:07 AM
Last Post: dm222
  loop (create variable where name is dependent on another variable) brianhclo 1 1,136 Aug-05-2022, 07:46 AM
Last Post: bowlofred
  breaking out of nested loops Skaperen 3 1,213 Jul-18-2022, 12:59 AM
Last Post: Skaperen
  Multiple Loop Statements in a Variable Dexty 1 1,200 May-23-2022, 08:53 AM
Last Post: bowlofred
Big Grin Variable flag vs code outside of for loop?(Disregard) cubangt 2 1,166 Mar-16-2022, 08:54 PM
Last Post: cubangt
  How to save specific variable in for loop in to the database? ilknurg 1 1,143 Mar-09-2022, 10:32 PM
Last Post: cubangt

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020