具有随机颜色和图例的 Matplotlib 散点

Matplotlib scatter points with random color and legend

菜鸟在这里,但我到处搜索,找不到任何提示来帮助我完成我正在尝试做的事情。我编写了一个 python 程序来创建马拉松游泳运动员的世界排名,并根据结果数据库生成任何给定日期的排名。我想创建一个看起来不蹩脚的图表,显示给定运动员的排名随时间推移的步数图,并叠加点来表示他们实际参加比赛的天数以及比赛内容。

这是我目前的情况:

dates = [list of consecutive dates]
ranks = [list of the athlete's rank of each of the dates in dates list]
race_dates = [list of dates athlete raced]
race_date_ranks = [list of the athlete's rank of each of the dates in race_date_ranks list]
race_labels = [list of races where the athlete raced (as string)]

plt.step(dates, ranks, where="post")
plt.plot(race_dates, race_date_ranks, "o")
for i, label in enumerate(race_labels):
    plt.text(race_dates[i], race_date_ranks[i], label, rotation=25, fontsize="x-small")

问题是......它看起来很糟糕并且难以辨认(抱歉,没有足够的状态点或 Whosebug 上的任何东西来嵌入......总有一天!)。我想要的是杀死上面的最后两行代码,从而删除标签,并让代表种族的每个点都是一个随机着色的点,没有标签。然后,添加带有圆点颜色和相应种族标签的图例。我怎样才能做到这一点?感谢您的帮助!

如果您有兴趣,这里有更多关于我的项目的信息: https://www.marathonswimworldrankings.com

我了解到此时的意图是消除字符串的重叠,改变每个比赛的颜色,并在图例中列出比赛名称。我创建的图表数据是通过从问题中的 link 检索数据创建的。由于比赛的名称未知,我使用了存档中 link 的名称。此外,由于如果有很多比赛名称,图例可能会从图中溢出,因此我指定了列数和图例顶部的位置。如果您担心与标题重叠,请在右侧添加多个列。

我个人认为,动画排名是一种使用网络技术的图表很好看,matplotlib阶梯图不太好看,所以使用ploty-dash等会更好。内容更丰富。

import pandas as pd
import requests

urls = ["https://docs.google.com/spreadsheets/d/1G2xBxmuigH0AqUg4XnkW4HPTLKt9gj6P5fO9RZnir4w/edit?usp=drive_web",
        "https://docs.google.com/spreadsheets/d/1CWKeG7QeIMQTLzmvTqif__4huX2oSub-NWaoVZsthJw/edit?usp=drive_web",
        "https://docs.google.com/spreadsheets/d/1dykR2toCcFZoWV2ytQkoYZ5YCPnFBhDPCPWeXOp-fiU/edit?usp=drive_web",
        "https://docs.google.com/spreadsheets/d/1r8xy9SyaLExivaWLHJvQTtIUTibJO2HqxYoS_JPq_fY/edit?usp=drive_web",
        "https://docs.google.com/spreadsheets/d/18GMsfJot0nD0bw6J2Kc7tKJ3R4blrwUqNaNxuqJgmxw/edit?usp=drive_web",
        "https://docs.google.com/spreadsheets/d/1E_Aal5ze-lLu-tYvKCoq6iK_-TWlPLfquocH0BrU4d4/edit?usp=drive_web",
        "https://docs.google.com/spreadsheets/d/1IEADAPFv-LE4dQkqBb60NnxBNdhUcxVdh3V0M1_dGmQ/edit?usp=drive_web",
        "https://docs.google.com/spreadsheets/d/1FTrt7-2RUGZrXpXiFKjD6XfOu31lFRHNYJjjnt-8YXY/edit?usp=drive_web"
       ]
compe_names = ["2022_03-31_men_10km","2022_02-28_men_10km","2022_01-31_men_10km","2021_12-31_men_10km",
               "2021_11-30_men_10km","2021_10-31_men_10km","2021_09-30_men_10km","2021_08-31_men_10km"]

data = pd.DataFrame([], columns=['name', 'pagerank', 'rank', 'competition'])
for url, compe in zip(urls, compe_names):
    r = requests.get(url)
    df_list = pd.read_html(r.text, index_col=0)
    df = df_list[0]
    df = df.loc[2:, ['A','B','C']]
    df.columns = ['name', 'pagerank', 'rank']
    df['competition'] = compe
    data = data.append(df, ignore_index=True)

data['date'] = data['competition'].apply(lambda x:x.rsplit('_',2)[0])
data['date'] = data['date'].str.replace('_', '-')
data['date'] = pd.to_datetime(data['date'])
data.sort_values('date', ascending=True, inplace=True)

data = data[data['name'] == 'Gregorio Paltrinieri']

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(12,3))

dates = data['date'].tolist()
ranks = data['rank'].tolist()

plt.step(dates, ranks, where="post")
for row in data.itertuples():
    plt.plot(row[5], row[3], "o", label=row[4])

plt.legend(ncol=4, loc=(0,1.05))
plt.show()