0

I have the below code, where I want user input to build a bar chart. However, the plot never actually reveals itself until the user exits the function?

def get_plot():
    while True:
        again = input("Do you want to visualise a player's pb scores?")
        if again == 'yes':          
            while True:
                player_name = input("What player do you want to visualise PB scores for the 19/20 season?").title() 
                if player_name in historics.values:
                    print("Player is present within the underlying data")
                    break
                else:
                    print("Player does not exist within the underlying data")

            is_player = historics['Player Name'] == player_name
            new_table = historics[is_player]

            #now we will use this data to produce a bar chart for this player, showing their pb scores over the 19/20 season
            def get_graph():
                plt.bar(new_table.Date,new_table['Matchday Score'],color="g")
                plt.title("%s's PB scores for 19/20 season" % player_name)
                plt.xlabel("Date")
                plt.ylabel("Matchday Score")
                if 'Forward' in new_table['FI Player Current Position'].values:
                    plt.axhline(y=255.56, color='gold', linestyle='-')
                    plt.axhline(y=239.94, color='slategrey', linestyle='-')
                    plt.axhline(y=173.52, color='saddlebrown', linestyle='-')
                elif 'Midfielder' in new_table['FI Player Current Position'].values:
                    plt.axhline(y=262.44, color='gold', linestyle='-')
                    plt.axhline(y=263.35, color='slategrey', linestyle='-')
                    plt.axhline(y=205.66, color='saddlebrown', linestyle='-')
                else:
                    plt.axhline(y=232.62, color='gold', linestyle='-')
                    plt.axhline(y=227.43, color='slategrey', linestyle='-')
                    plt.axhline(y=182.36, color='saddlebrown', linestyle='-')
                plt.rcParams["figure.figsize"]=10,5
                plt.show()
            get_graph()
        if again == 'no':
            break
        else:
            print("Please provide a valid value")
    
get_plot()

So after the input of "no" is provided, the plot of the last provided player_name value is displayed. However, I want the plot to be created (and displayed) upon the entry of the player_name value, and for the plot to be refreshed upon each subsequent value provided?

Where am I going wrong?

Thanks.

EDIT: An example of the data (historics.head()):

        Date       Player Name       Team Name           Opposition  \
0 2020-08-23    Kingsley Coman  Bayern München  Paris Saint Germain   
1 2020-08-23    Joshua Kimmich  Bayern München  Paris Saint Germain   
2 2020-08-23  Thiago Alcántara  Bayern München  Paris Saint Germain   
3 2020-08-23      Manuel Neuer  Bayern München  Paris Saint Germain   
4 2020-08-23       David Alaba  Bayern München  Paris Saint Germain   

  Home or Away?       Competition Starting Lineup? Formation  \
0          Away  Champions League           Lineup   4-2-3-1   
1          Away  Champions League           Lineup   4-2-3-1   
2          Away  Champions League           Lineup   4-2-3-1   
3          Away  Champions League           Lineup   4-2-3-1   
4          Away  Champions League           Lineup   4-2-3-1   

   Matchday Dividends FI Game Position  ... Interceptions Blocks  Clearances  \
0                0.18          Forward  ...           0.0    0.0         0.0   
1                0.10       Midfielder  ...           1.0    1.0         1.0   
2                0.00       Midfielder  ...           2.0    0.0         0.0   
3                0.00       Goalkeeper  ...           0.0    0.0         0.0   
4                0.00         Defender  ...           1.0    0.0         2.0   

   Offsides  Fouls Committed  Yellow Cards  Red Card (Two Yellows)  \
0       0.0              0.0           0.0                     0.0   
1       0.0              1.0           0.0                     0.0   
2       NaN              4.0           0.0                     0.0   
3       0.0              0.0           0.0                     0.0   
4       0.0              0.0           0.0                     0.0   

   Straight Red Cards  Goals Conceded (GKs)  \
0                 0.0                   0.0   
1                 0.0                   0.0   
2                 0.0                   0.0   
3                 0.0                   0.0   
4                 0.0                   0.0   

   Different Game Position to Current FI Position?  
0                                                1  
1                                                1  
2                                                0  
3                                                0  
4                                                0  
Mullins
  • 67
  • 9

1 Answers1

1

There are two factors to this question:

On one hand, you will not be able to keep executing code after showing a plot, unless you are using the interactive mode of matplotlib, which can be activated by using plt.ion(). Please check this question.

On another hand, if you want to update a plot based on user input, you should start by creating a plot, and saving that reference to update the figure every time the user provides a new player_name. Please check this question, and its accepted answer.

I've made a quick example that I tested with the data you provided:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


def plot_player_stats(player_name, historics, fig, ax):
    # validate player name
    if player_name not in historics.values:
        print("Sorry! Unknown player!")
        return

    # search player stats
    is_player = historics['Player Name'] == player_name
    player_stats = historics[is_player]

    # draw bar plot
    ax.clear()
    ax.bar(player_stats.Date, player_stats['Matchday Score'], color="g")
    ax.set_title("%s's PB scores for 19/20 season" % player_name)
    ax.set_xlabel("Date")
    ax.set_ylabel("Matchday Score")

    # ... add lines ...
    plt.draw()


def start_main_plot_loop():

    # load data
    historics = pd.read_csv('sample.csv')

    # initialize plot
    fig, ax = plt.subplots()

    # start loop
    while True:
        player_name = input("Please select a player's name (empty to stop): ")
        if not player_name:
            print("Thanks! See ya soon ma mate!")
            break

        plot_player_stats(player_name, historics, fig, ax)


if __name__ == '__main__':
    plt.ion()
    start_main_plot_loop()

Save the ax when creating a subplot and clear it every time you need to draw a new bar plot.

EDIT:

If you are trying to run this on a Jupyter Notebook, the only thing I could do to make it work is the following:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from IPython.display import clear_output # <---- import this function


def plot_player_stats(player_name, historics):
    # validate player name
    if player_name not in historics.values:
        print("Sorry! Unknown player!")
        return

    # search player stats
    is_player = historics['Player Name'] == player_name
    player_stats = historics[is_player]

    # draw bar plot
    plt.bar(player_stats.Date, player_stats['Matchday Score'], color="g")
    plt.title("%s's PB scores for 19/20 season" % player_name)
    plt.xlabel("Date")
    plt.ylabel("Matchday Score")

    # ... add lines ...

    clear_output() # <---- this will clear all cell output!
    plt.show()


def start_main_plot_loop():

    # load data
    historics = pd.read_csv('sample.csv')

    # start loop
    while True:
        player_name = input("Please select a player's name (empty to stop): ")
        if not player_name:
            print("Thanks! See ya soon ma mate!")
            break

        plot_player_stats(player_name, historics)

if __name__ == '__main__':
    start_main_plot_loop()

As a side effect, the clear_output function will clear all the printed output within the cell. Let me know if this is helpful!

rusito23
  • 995
  • 8
  • 20
  • Thanks for the suggestion! Unfortunately it's only producing a plot (in my Jupyter Notebooks) when you exit the function. So still not getting the ability to build the plot, see it, then clear it and rebuild it. – Mullins Sep 09 '20 at 16:53
  • @JacobStafford oh I didn't know that you were using a jupyter notebook, did you consider clearing the cell output every the plot is updated? Do you need to keep the previously selected player names in the cell output? – rusito23 Sep 09 '20 at 18:32
  • @JacobStafford I updated my response with a workaround using `clear_output`for Jupyter Notebooks – rusito23 Sep 09 '20 at 18:41
  • Amazing!! Works a charm. Thanks a bunch. – Mullins Sep 09 '20 at 21:13
  • Great @JacobStafford, I'm glad it worked! Please remember to mark the answer as accepted so it can help other users in the future! – rusito23 Sep 10 '20 at 16:14