So I am trying to plot curved lines to join points, here is the code I am using:-
def hanging_line(point1, point2):
a = (point2[1] - point1[1])/(np.cosh(point2[0]) - np.cosh(point1[0]))
b = point1[1] - a*np.cosh(point1[0])
x = np.linspace(point1[0], point2[0], 100)
y = a*np.cosh(x) + b
return (x,y)
n_teams = 4
n_weeks = 4
fig, ax = plt.subplots(figsize=(6,6))
t = np.array([
[1, 2, 4, 3],
[4, 3, 3, 2],
[3, 4, 1, 4],
[2, 1, 2, 1]
])
fig.patch.set_facecolor('#1b1b1b')
for nw in range(n_weeks):
ax.scatter([nw] * n_weeks, t[:, nw], marker='o', color='#4F535C', s=100, zorder=2)
ax.axis('off')
for team in t:
x1, x2 = 0, 1
for rank in range(0, len(team) - 1):
y1 = n_weeks - team[rank] + 1
y2 = n_weeks - team[rank + 1] + 1
x, y = hanging_line([x1, y1], [x2, y2])
ax.plot(x, y, color='#4F535C', zorder=1)
x1 += 1
x2 += 1
The code is producing the following output:- 
But I want the curved lines to look somewhat like this: 
What changes should I have to do in my code to get the required result?
Here is an approach using bezier curves.
The sequence [...., i-indent, i, i + 0.8, ...]
will put control points at each integer position i
and some space before and after. The plot below used indent=0.8
; indent=0
would create straight lines; with indent>1
the curves would be intersecting more. Other variations will make the curves more or less "cornered".
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
import numpy as np
n_teams = 4
n_weeks = 4
t = np.array([[1, 2, 4, 3],
[4, 3, 3, 2],
[3, 4, 1, 4],
[2, 1, 2, 1]])
fig, ax = plt.subplots(figsize=(10, 4), facecolor='#1b1b1b')
ax.set_facecolor('#1b1b1b')
indent = 0.8
for tj in t:
ax.scatter(np.arange(len(tj)), tj, marker='o', color='#4F535C', s=100, zorder=3)
# create bezier curves
verts = [(i + d, tij) for i, tij in enumerate(tj) for d in (-indent, 0, indent)][1:-1]
codes = [Path.MOVETO] + [Path.CURVE4] * (len(verts) - 1)
path = Path(verts, codes)
patch = patches.PathPatch(path, facecolor='none', lw=2, edgecolor='#4F535C')
ax.add_patch(patch)
ax.set_xticks([])
ax.set_yticks([])
ax.autoscale() # sets the xlim and ylim for the added patches
plt.show()

A colored version could look like:
colors = ['crimson', 'skyblue', 'lime', 'gold']
for tj, color in zip(t, colors):
ax.scatter(np.arange(len(tj)), tj, marker='o', color=color, s=100, zorder=3)
verts = [(i + d, tij) for i, tij in enumerate(tj) for d in (-indent, 0, indent)][1:-1]
codes = [Path.MOVETO] + [Path.CURVE4] * (len(verts) - 1)
path = Path(verts, codes)
patch = patches.PathPatch(path, facecolor='none', lw=2, edgecolor=color)
ax.add_patch(patch)

The following plot compares different values for indent
:

所有评论(0)