[NOT HAPPENING] Oumar Solet

Discussion in 'The Transfer List' started by Stuey, Sep 25, 2024.

  1. Stuey

    Stuey Reservist

  2. The undeniable truth

    The undeniable truth First Team Captain

    Wonder why his contract was terminated between transfer windows. Seems odd as he can’t play for over 3 months?
    Gives Udinese time to assess whether he’s good enough to keep or bad enough to send to us.
     
  3. Lubaduck

    Lubaduck Reservist

    We gotta get him in
    "Ohhhh Solet Solet .......etc"
    Middle of the Road ......ask your Grandad !
     
    Moose likes this.
  4. The undeniable truth

    The undeniable truth First Team Captain

    Oumar gawd. There's nothing like this ?
    1991.
     
  5. lowerrous

    lowerrous Guest

    Former France youth international. Seemed to play fairly regularly for RB Salzburg in recent seasons. Seems a bit odd that he was released and I'd have thought he'd probably be out of reach for us and rather a signing for Udinese. But who knows, maybe Porteous' recent displays have got us worried and already planning an urgent upgrade?

    Any stats for his last season @reids ? fbref doesn't seem to cover the Austrian Bundesliga.
     
  6. UEA_Hornet

    UEA_Hornet First Team Captain

    I'm sure it was just his agent drumming up business but on the usual rumour-touting sites he was linked with Man Utd, Villa, West Ham etc only this summer. I can't imagine he'd be keen to come here unless we somehow got promoted.
     
  7. reids

    reids First Team

    [​IMG]

    :eek::eek::eek::eek::eek::eek:
     
  8. UEA_Hornet

    UEA_Hornet First Team Captain

    Not coming here then. Next!
     
    lowerrous likes this.
  9. GoingDown

    GoingDown "The Stability"

    3 metres tall and a foot like a traction engine.
     
  10. The undeniable truth

    The undeniable truth First Team Captain

    Apparently TC has said "No thanks, I'm happy with Tikvic".
     
    Vanhorn17, CYHSYF and wfcwarehouse like this.
  11. Heidar

    Heidar Squad Player

    So he's the best defender in the world? Interesting
     
  12. The undeniable truth

    The undeniable truth First Team Captain

    I always tend to look at the shape of these rather than the scales and actual values. I mean do all of these radars have 0.27 as the max "OBV" stat (whatever that is !??) or is 0.27 actually pretty crap and good players are 0.75 or something....???
     
  13. The Voice of Reason

    The Voice of Reason First Team Captain

    Quite frankly I don't understand them :confused:
     
    Hairyfrog likes this.
  14. reids

    reids First Team

    Yeah, all templates for each position will have the same values listed at the same points - so every radar for that position is comparable. He's actually got 0.31 OBV which goes off the scale - which puts him in the top 2% of all CBs. OBV stands for on-ball value and it basically quantifies every single action each player makes to give a value as to whether that action is likely to make his team more/less likely to score a goal. This probably explains it better than I could:



    They basically take a bunch of stats that are useful in that players position and compares them against every other player in the world who also plays in that position. The more colours = the better that player is in that particular statistic. A nice way to try and learn from is Haaland (as well as most people knowing what he does pretty well!). You can see some stats are very coloured and others have practically nothing in them. So from this we can see that:

    - He takes a LOT of shots (as it's coloured in pretty much at the max!) compared to most strikers
    - He presses quite a lot (as the pressures + pressures regains stats are very coloured in)
    - He's not a very good dribbler (or doesn't try to dribble that much) as the "successful dribbles" stat is basically nothing


    [​IMG]
     
  15. The undeniable truth

    The undeniable truth First Team Captain

    Thanks. You know your stuff ! Must feel out of place on here :).
     
    põder and reids like this.
  16. reids

    reids First Team

    Dunno whether you like/play chess but to simplify it for myself, I think of OBV as like a chess calculator/analyser - that tells you how each move (compared the positions of all the other pieces on the board) likely affects your chance of winning, then just replace chess with football and winning with scoring!
     
    dhk and sydney_horn like this.
  17. The Voice of Reason

    The Voice of Reason First Team Captain

    Perhaps if it was not a pie chart, but upright line chart, it would be easier to read?
     
  18. Chumlax

    Chumlax Squad Player

    99.9% sure you won't be able to read this anyway, but how hard is it, exactly, to comprehend that the further out the colour goes towards the edge of the circle at each point, the stronger the player is at that particular attribute?
     
    GoingDown likes this.
  19. The Voice of Reason

    The Voice of Reason First Team Captain

    It's the attribute titles which are hard to read :p
     
    Chumlax likes this.
  20. SkylaRose

    SkylaRose Administrator Staff Member

    Wait till @reids starts writing his own software in R. His stats will be through the roof with graphs, diagrams and colour coded spread sheets/databases. Sofascore won't be able to touch it! :p
     
  21. reids

    reids First Team

    If I ever get time to get past anything else than installing it :( that being said, I've been given some code in Python that I have to edit each week that queries SB data to produce automated reports so I am getting a bit more comfortable in that regard!

    [​IMG]
     
    SkylaRose and watto1 like this.
  22. wfcmoog

    wfcmoog Tinpot

    weak tack/dribble past stats, which I know is a priority for Clevs.
     
  23. SkylaRose

    SkylaRose Administrator Staff Member

    You got that from a load of jumbled Python Code? (no offense I cannot stand Python scripts ;)) Very impressive! Thankfully I never have to handle databases (but I know how to write one if I had to) in my work but I do query them via a third party Ada library that uses a bind package from SQL. When you get a grasp of R you will understand how efficient it really is in not only presenting and displaying data, but hiding it from other files, sorting it and maintaining it 1000% better than Python ever will.
     
  24. Since63

    Since63 Squad Player

    In a broken dream?
     
  25. lowerrous

    lowerrous Guest

    Let's pray that this guy is coming to replace Porteous in January.
     
  26. reids

    reids First Team

    I don't know what you mean - it's easy!


    Code:
    team="Tenerife" #must be same spelling as appears in StatsBomb IQ
    competition=42 #StatsBomb's competition id
    season=317 #StatsBomb's season id
    league="La Liga 2" #this is for the viz title, call it what you like
    season_title="2024/25"
    
    #you can change any of the colours on the data viz should you wish to do so
    bgcolor="white"
    textc="black"
    white="white"
    sbred='#e21017'
    lightgrey="#d9d9d9"
    darkgrey='#9A9A9A'
    linec=darkgrey
    cmaplist = [white, darkgrey, sbred]
    
    pip install statsbombpy
    pip install mplsoccer
    from statsbombpy import sb
    import pandas as pd
    import numpy as np
    from mplsoccer import VerticalPitch, add_image
    import matplotlib.pyplot as plt
    from matplotlib.colors import LinearSegmentedColormap
    import matplotlib.patheffects as path_effects
    import matplotlib.font_manager as font_manager
    from scipy.ndimage import gaussian_filter
    from matplotlib import patches
    import warnings
    warnings.filterwarnings("ignore")
    
    #Choosing matches from competitions and season
    matches = sb.matches(competition_id= competition, season_id=season,
                         creds={"user": email, "passwd": password})
    
    team_matches = matches[(matches['home_team'] == team)|(matches['away_team'] == team)]
    team_matches = team_matches[team_matches["match_status"]=="available"]
    team_matches = team_matches.sort_values(by=['match_date'])
    list_matches = team_matches.match_id.tolist()
    
    #load events from specific matches (faster than pulling a whole competition season)
    events = []
    for n in list_matches:
        match_events = sb.events(match_id = n,creds={"user": email, "passwd": password})
        events.append(match_events)
    events=pd.concat(events)
    
    #filtering by specific event -> corners
    corners = events[events["pass_type"] == "Corner"]
    
    ### parse relevant columns to get start and end point of actions
    corners[['x', 'y']] = corners['location'].apply(pd.Series)
    corners[['pass_end_x', 'pass_end_y']] = corners['pass_end_location'].apply(pd.Series)
    
    #filling blank cells with short corner technique
    corners['pass_technique'] = corners['pass_technique'].fillna("Short")
    
    #filter dataframe to get only corners by focus team
    focus_corners=corners[(corners['team'] == team)]
    
    #identify corners by backpost, frontpost and penspot
    conditions=[((abs(focus_corners['y']-focus_corners['pass_end_y'])) > 43)
        & (focus_corners['pass_technique']!="Short")]
    values=[1]
    focus_corners['backpost']=np.select(conditions, values)
    
    conditions=[((abs(focus_corners['y']-focus_corners['pass_end_y'])) < 37 )
        & (focus_corners['pass_technique']!="Short")]
    values=[1]
    focus_corners['frontpost']=np.select(conditions, values)
    
    conditions=[(focus_corners['backpost']==0) & (focus_corners['frontpost']==0)
        & (focus_corners['pass_technique']!="Short")]
    values=[1]
    focus_corners['penspot']=np.select(conditions, values)
    
    #separating by left and right corners in own team and also in opposition team
    left_corners=focus_corners[(focus_corners['y']<=40) & (focus_corners['x']>=60)]
    right_corners=focus_corners[(focus_corners['y']>=40) & (focus_corners['x']>=60)]
    
    def get_corner_stats (data):
    
        #get total corners
        total=len(data)
    
        # shot, front, back
        short=len(data[(data['pass_technique']=='Short')])*100
        short=round(short/total,1)
        backpost=len(data[(data['backpost']==1)])*100
        backpost=round(backpost/total,1)
        frontpost=len(data[(data['frontpost']==1)])*100
        frontpost=round(frontpost/total,1)
        penspot=len(data[(data['penspot']==1)])*100
        penspot=round(penspot/total,1)
    
        #six-yard, deeper
        sixyard=len(data[(data['pass_end_x']>=114)&(data['pass_technique']!='Short')])*100
        sixyard=round(sixyard/total,1)
        deeper=len(data[(data['pass_end_x']<114)&(data['pass_technique']!='Short')])*100
        deeper=round(deeper/total,1)
    
        goals=len(data[(data['pass_goal_assist']==True)])
        shots_df=data[(data['pass_shot_assist']==True)]
        shots=len(shots_df)
        total_corners=len(data)
    
        shot_ids=shots_df.pass_assisted_shot_id.tolist()
    
        if len(shot_ids)>0:
            xg_df = []
            for n in shot_ids:
                xg_shot = events[(events['id']==n)]
                xg_df.append(xg_shot)
            xg_df=pd.concat(xg_df)
    
            xg=round(xg_df.shot_statsbomb_xg.sum(),2)
        else:
            xg=0
    
        if data.y.mean()>=40:
            side="right"
        else:
            side="left"
    
        return side, total, short, backpost, frontpost, penspot, sixyard, deeper, goals, shots, total_corners, xg
    
    #define function for removing axis on subplots
    def customise_plot(ax):
        for n in ["right","top","left","bottom"]:
            ax.spines[n].set_visible(False)
            ax.patch.set_facecolor(bgcolor)
            ax.tick_params(bottom=False,top=False,labelbottom=False)
    
    #create bar chart
    def plot_bar (data,groupby,taker_or_target,ax):
    
        target = data.groupby([groupby]).size()
        target=target.reset_index()
        target.rename(columns={target.columns[1]: taker_or_target }, inplace = True)
        target=target.sort_values(taker_or_target, ascending=False)
        target = target.head(5)
        target=target.sort_values(taker_or_target)
    
        bars = target[groupby]
        h = target[taker_or_target]
        y_pos = np.arange(len(bars))
    
        ax.barh(y_pos, h, color=sbred, edgecolor=darkgrey)
    
        # Create names on the x-axis
        ax.set_yticks(y_pos)
        ax.set_yticklabels(bars,color=textc,size=24)
    
        customise_plot(ax)
    
        text=target[taker_or_target].astype(int)
        for i, v in enumerate(text):
                ax.text(v*0.9, i-0.09, str(v), color=textc, fontsize=28,fontweight="bold",ha='center')
    
    #plotting the data
    def plot_corners (data,axA,axB,axC):
    
        #calculate data points
        side, total, short, backpost, frontpost, penspot, sixyard, deeper, goals, shots, total_corners, xg = get_corner_stats (data)
    
        #create a new dataframe that doesn't include short corners
        non_short_df=data.loc[(data['pass_technique']!='Short')]
    
        #create heatmap of end point of crosses
        bin_statistic=pitch.bin_statistic(non_short_df['pass_end_x'], non_short_df['pass_end_y'], statistic='count', bins=(40,30))
        bin_statistic['statistic'] = gaussian_filter(bin_statistic['statistic'], 1)
        pitch.heatmap(bin_statistic, edgecolors=bgcolor, cmap=cmap, ax=axA,alpha=0.75)
    
        if side=="left":
            x1_label=26.9 #front post
            x2_label=52.9 #back post
            x3_label=79.9 #6-yard/deeper
            x4_label=3 #short corner
            x4_circle=0 #start point
    
            total=len(data)
            inswinger=len(data.loc[(data['pass_technique']=="Inswinging")])
            inswinger=int(inswinger/total*100)
            lw_i=inswinger/10
    
            outswinger=len(data.loc[(data['pass_technique']=="Outswinging")])
            outswinger=int(outswinger/total*100)
            lw_o=outswinger/10
    
            #inswinger
            style = "Simple, tail_width=0.5, head_width=16, head_length=12"
            a1 = patches.FancyArrowPatch((x4_circle,120), (25,105),
                                     connectionstyle="arc3,rad=.2", color=darkgrey,arrowstyle=style,
                                     lw=lw_i,zorder=5,alpha=1)
            axA.add_patch(a1)
    
            #outswinger
            a2 = patches.FancyArrowPatch((x4_circle,120), (25,110),
                                     connectionstyle="arc3,rad=-0.28", color=darkgrey,arrowstyle=style,
                                     lw=lw_o,zorder=5,alpha=1)
            axA.add_patch(a2)
    
            axA.text(s=f"Inswinger: {inswinger}%",x=x4_circle-5,y=105,size=26,color=darkgrey,ha="center",fontweight='bold')
            axA.text(s=f"Outswinger: {outswinger}%",x=x4_circle-5,y=125,size=26,color=darkgrey,ha="center",fontweight='bold')
    
    
        elif side=="right":
            x1_label=52.9
            x2_label=26.9
            x3_label=3
            x4_label=79.9
            x4_circle=80
    
            total=len(data)
            inswinger=len(data.loc[(data['pass_technique']=="Inswinging")])
            inswinger=int(inswinger/total*100)
            lw_i=inswinger/10
    
            outswinger=len(data.loc[(data['pass_technique']=="Outswinging")])
            outswinger=int(outswinger/total*100)
            lw_o=outswinger/10
    
            #outswinger
            style = "Simple, tail_width=0.5, head_width=16, head_length=12"
            a1 = patches.FancyArrowPatch((x4_circle,120), (55,110),
                                     connectionstyle="arc3,rad=.2", color=darkgrey,arrowstyle=style,
                                     lw=lw_o,zorder=5,alpha=1)
            axA.add_patch(a1)
    
            #inswinger
            a2 = patches.FancyArrowPatch((x4_circle,120), (55,105),
                                     connectionstyle="arc3,rad=-0.28", color=darkgrey,arrowstyle=style,
                                     lw=lw_i,zorder=5,alpha=1)
            axA.add_patch(a2)
    
            axA.text(s=f"Inswinger: {inswinger}%",x=x4_circle+5,y=105,size=26,color=darkgrey,ha="center",fontweight='bold')
            axA.text(s=f"Outswinger: {outswinger}%",x=x4_circle+5,y=125,size=26,color=darkgrey,ha="center",fontweight='bold')
    
    
        #add circle to highlight which side the corner is taken from
        a_circle = plt.Circle((x4_circle, 120), 3, zorder=5, fill=False,edgecolor=sbred,lw=5,ls="-")
        axA.add_artist(a_circle)
    
    
    
    
        #plot data relating to target areas
        axA.text(s=f"Total corners: {total}",x=40,y=128,size=32,color=textc,ha='center')
        axA.text(s=f"Front post: {frontpost}%",x=x1_label,y=63,size=28,color=textc,rotation=270,ha="center",path_effects=path_eff)
        axA.text(s=f"Middle: {penspot}%",x=40,y=63,size=28,color=textc,rotation=270,ha="center",path_effects=path_eff)
        axA.text(s=f"Back post: {backpost}%",x=x2_label,y=63,size=28,color=textc,rotation=270,ha="center",path_effects=path_eff)
    
        axA.axvline(x=37, ymin=0.5, ymax=0.875,color=darkgrey, lw=3, linestyle='--')
        axA.axvline(x=43, ymin=0.5, ymax=0.875,color=darkgrey, lw=3, linestyle='--')
        axA.text(s=f"6 yard box: {sixyard}%",x=x3_label,y=115,size=28,color=textc,ha="center",path_effects=path_eff)
        axA.text(s=f"Deeper: {deeper}%",x=x3_label,y=107,size=28,color=textc,ha="center",path_effects=path_eff)
        axA.text(s=f"Short\ncorners: {short}%",x=x4_label,y=92.5,size=24,color=textc,ha="center",path_effects=path_eff)
        axA.text(s=f"Goals: {goals} | Shots: {shots} | xG: {xg}",x=40,y=122,size=30,color=sbred,ha="center")
    
        #BAR CHART for first contacts
        plot_bar (non_short_df,'pass_recipient','target',axB)
    
        #BAR CHART for corner kick takers
        plot_bar (data,'player','corners_taken',axC)
    
    
    
    #set dimensions of the pitch
    pitch = VerticalPitch(half=True,pitch_color=bgcolor, line_color=linec,line_zorder=1,pad_top=10)
    
    cmap = LinearSegmentedColormap.from_list("", cmaplist)
    path_eff = [path_effects.Stroke(linewidth=2, foreground=darkgrey), path_effects.Normal()]
    
    #set figure size and dimensions
    fig = plt.figure(figsize=(40,30),constrained_layout=True)
    gs = fig.add_gridspec(nrows=3,ncols=4)
    fig.patch.set_facecolor(bgcolor)
    
    #plot results for left side corners
    ax1 = fig.add_subplot(gs[0,1:3])
    ax1.set_title(label="Corners from left",x=0.5,y=1.04,size=30,color=textc,ha='center',fontweight='bold')
    pitch.draw(ax=ax1)
    ax2 = fig.add_subplot(gs[0,3])
    ax2.set_title(label="Top 5 - Intended targets\ncontact from left\n(short corners excluded)",x=0.5,y=1.02,size=26,color=textc,ha='center',fontweight='bold')
    ax3 = fig.add_subplot(gs[0,0])
    ax3.set_title(label="Top 5 - Corner takers from left",x=0.5,y=1.02,size=26,color=textc,ha='center',fontweight='bold')
    plot_corners (left_corners,ax1,ax2,ax3)
    
    #plot results for right side corners
    ax4 = fig.add_subplot(gs[1,1:3])
    ax4.set_title(label="Corners from right",x=0.5,y=1.04,size=30,color=textc,ha='center',fontweight='bold')
    pitch.draw(ax=ax4)
    ax5 = fig.add_subplot(gs[1,3])
    ax5.set_title(label="Top 5 - Intended targets\ncontact from right\n(short corners excluded)",x=0.5,y=1.02,size=26,color=textc,ha='center',fontweight='bold')
    ax6 = fig.add_subplot(gs[1,0])
    ax6.set_title(label="Top 5 - Corner takers from right",x=0.5,y=1.02,size=26,color=textc,ha='center',fontweight='bold')
    plot_corners (right_corners,ax4,ax5,ax6)
    
    #set titles
    fig.text(s=f"{team} Corners | {league} {season_title}", #ha='center'
    x=0.02, y =1.1, fontsize=54,color=textc,fontweight='bold')
    
    fig.text(s="Goals, Shots and xG data refer to first point of contact from corner.\nFor the purposes of this data visualisation a short corner is any corner not tagged as outswinging, inswinging\nor straight - this may include corners that are ‘clipped’ to the edge of the box, or otherwise.", #ha='center'
    x=0.02, y =1.03, fontsize=36,color=sbred)
    
    Hmm, maybe not
     
    SkylaRose likes this.
  27. SkylaRose

    SkylaRose Administrator Staff Member

    My point stands on how confusing Python is to read via scripting. ;) I do appreciate the consistency of the code flow, that is a plus. However I hate the way arrays are designed like that. I mean it's difficult from looking at the code to understand what the array can hold, what is does hold, does it have any limits and most importantly, does it handle overloading or 'buffer overflows' in a way the programmer can act/react to them. This might all be handled under-the-hood via language specification (I don't use Python so I am guessing) but surely implementing a form of exception handling to avoid memory leaks would be a good idea.
     
  28. Moose

    Moose First Team Captain

    Will sign for us and then, in a remarkable move, be sold to Udinese for £25m, then loaned back to us.
     
  29. The undeniable truth

    The undeniable truth First Team Captain

    Happy with that.
     
    Moose likes this.
  30. Hogg-DEENEY!!!

    Hogg-DEENEY!!! First Team

    Nothing more than £50m is acceptable to me if you’re listening Giampaolo
     
  31. SkylaRose

    SkylaRose Administrator Staff Member

    He's an semi-active member of this community. Sometimes comes out of Hibernation to protect his son from any fault.
     
  32. reids

    reids First Team

    Has joined Udinese.
     
  33. Steve Leo Beleck

    Steve Leo Beleck Squad Player

    Frees up Kabasele to return in Jan. #localmanisback
     
    The undeniable truth likes this.
  34. Knight GT

    Knight GT Predictor extraordinaire 2013/14

    Why on earth was he released?
     
  35. reids

    reids First Team

    Did a bit of digging cos none of it made sense. Apparently there's been a fair few issues. He was highly aware of PL interest in the final months of the season so was (apparently) quite "unprofessional" in those last couple of months. They sent him to train with their 2nd team in the Austrian 2nd tier as a result. Apparently failed medicals at both Hoffenheim and West Ham over the summer, so with his contract expiring next year (and foreign clubs able to negotiate that free deal in January) I reckon they'd had enough and knew any chance of getting a fee for him was unlikely so negotiated his exit.

    Basically a peak Pozzo signing: Free? Check. Bit of a ****? Check. Injury issues? Check.
     

Share This Page