Nested for loops - help with iterating a variable outside of the main loop - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Nested for loops - help with iterating a variable outside of the main loop (/thread-37981.html) |
Nested for loops - help with iterating a variable outside of the main loop - dm222 - Aug-17-2022 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) 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) 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) 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() 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
RE: Nested for loops - deanhystad - Aug-17-2022 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: And this is what Python thinks the error is: 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: And this is what Python thinks the error is: If you look at the documentation you would see that it does't have a fontsize argument.https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html if you have additional questions please ask them as new posts to this thread. Do not edit your original post. RE: Nested for loops - dm222 - Aug-17-2022 (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. 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: It's good for me to read and understand your error/explanation reply, thank you.
RE: Nested for loops - dm222 - Aug-17-2022 (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. 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. RE: Nested for loops - help with iterating a variable outside of the main loop - deanhystad - Aug-17-2022 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. |