def half_pitch(fig):
L = dict(color=LINE, width=2)
shapes = [
dict(type="rect", x0=52.5, y0=0, x1=105, y1=68, line=L),
dict(type="rect", x0=88.5, y0=13.84, x1=105, y1=54.16, line=L),
dict(type="rect", x0=99.5, y0=24.84, x1=105, y1=43.16, line=L),
dict(type="line", x0=105, y0=30.34, x1=105, y1=37.66, line=dict(color=INK, width=5)),
dict(type="path", path="M 52.5 24.85 A 9.15 9.15 0 0 1 52.5 43.15", line=L),
dict(type="path", path="M 88.5 26.69 A 9.15 9.15 0 0 0 88.5 41.31", line=L),
]
fig.add_trace(go.Scatter(x=[94], y=[34], mode="markers", marker=dict(color=LINE, size=5),
hoverinfo="skip", showlegend=False))
fig.update_layout(shapes=shapes)
fig.update_xaxes(range=[51.5, 106.5], visible=False, fixedrange=True)
fig.update_yaxes(range=[-1, 69], visible=False, scaleanchor="x", scaleratio=1, fixedrange=True)
return fig
c = shots[shots.team == "Chelsea"].copy()
c["px"], c["py"] = c.x * 105, c.y * 68
c["dist"] = np.hypot(105 - c.px, 34 - c.py).round(0).astype(int)
c["goal"] = c.result == "Goal"
c["is_h"] = c.player == "Jordan Henderson"
fig = half_pitch(go.Figure())
for is_h, name in ((False, "Other Chelsea shots"), (True, "Jordan Henderson")):
for goal in (False, True):
d = c[(c.is_h == is_h) & (c.goal == goal)]
if d.empty:
continue
col = RED if is_h else CONTEXT
fig.add_trace(go.Scatter(
x=d.px, y=d.py, mode="markers", name=name, legendgroup=name,
showlegend=goal or d.empty,
marker=dict(size=10 + d.xg * 60, color=col if goal else "rgba(0,0,0,0)",
line=dict(color=col, width=2.5),
symbol="circle"),
customdata=d[["player", "minute", "xg", "result", "situation", "dist", "assisted_by"]].fillna("").values,
hovertemplate="<b>%{customdata[0]}</b>, %{customdata[1]}'<br>%{customdata[3]} · xG %{customdata[2]:.3f}"
"<br>%{customdata[4]} · %{customdata[5]} m from goal"
"<br>Assist: %{customdata[6]}<extra></extra>"))
for _, r in c[c.is_h & c.goal].iterrows():
fig.add_annotation(x=r.px, y=r.py, text=f"{r.minute}' · xG {r.xg:.2f}", showarrow=True,
arrowhead=0, ax=-70, ay=-34 if r.py > 30 else 34,
font=dict(color=INK, size=12), arrowcolor=MUTED, bgcolor="rgba(255,255,255,.85)")
style(fig, height=520, legend=dict(orientation="h", y=-0.02, x=0.5, xanchor="center"))
fig.show(config=CONFIG)