Skip to content

Latest commit

 

History

History
143 lines (72 loc) · 15.9 KB

improving-the-strava-training-log-4d2039c49ec4.md

File metadata and controls

143 lines (72 loc) · 15.9 KB

改进 Strava 训练日志

原文:towardsdatascience.com/improving-the-strava-training-log-4d2039c49ec4

使用 Strava、Python 和 Matplotlib 进行马拉松跑者训练模式的可视化。

barrysmythTowards Data Science barrysmyth

·发布于 Towards Data Science ·12 分钟阅读·2023 年 11 月 16 日

--

作为一名马拉松跑者,我使用 Strava。非常多。这是一个很棒的应用程序。除了所有常见的社交功能(分享活动、了解朋友的动态、查看俱乐部的活动等),我依赖 Strava 跟踪我的所有活动,并定期使用它来分析我的训练进展。或者说我尽力而为。我喜欢使用 Strava 的训练日志 来查看我当前的训练情况,相较于以前的年份,但遗憾的是,这不是 Strava 真正强项的地方,尽管训练日志是一个高级功能。

问题的一部分是训练日志提供的信息非常有限。例如,在下面的示例训练日志中,我们可以看到几周的活动记录(彩色圆圈),这些记录总结了训练活动的频率和距离,但没有关于训练强度或努力的任何信息。因此,我认为研究如何改进这一点将是一个有趣的副项目……

作者的 Strava 训练日志的一部分;截图由作者制作。

我将从讨论我对 Strava 当前训练日志中缺失内容的看法开始,并建议如何将这些缺失的信息添加到重新构想的训练日志可视化中。我将描述如何实现这一点,使用 Python 和 Matplotlib 的示例,并最终展示一个使用我自己都柏林马拉松 2023 年训练数据的具体结果示例。

动机

上面的 Strava 训练日志示例展示了我今年(2023 年)为都柏林马拉松训练的最后 4 周。每一行对应一周的训练,每一列对应一周中的不同天。我训练的日子通过颜色编码的圆圈表示,显示了当天完成的距离。红色圆圈表示比赛。深绿色圆圈表示长跑。阴影绿色圆圈表示训练 — 通常是更复杂的多部分间歇训练 — 而浅绿色圆圈表示既不是长跑也不是训练的常规跑步。所有这些类别都是由跑者手动分配的。最后,左侧列显示了相关的日期信息和每周的总距离。

这是总结几周训练的一个完全合理且视觉上吸引人的方法。然而,它仅提供了训练的一个非常有限的快照。它仅关注活动频率和训练量(距离)——这当然是相关的——但没有关于训练强度或努力的信息。例如,没有配速或心率(HR)信息,除非它恰好包含在跑者提供的会话标题中,即使如此,这也可能不是会话期间实际情况的可靠指示。没有这些信息,很难评估训练进展,更难比较一周的训练与另一周的训练,更不用说今年的训练与早期年份的训练相比,因为跑步距离只讲述了部分故事。

目标

让我们通过增强这个基本可视化来改进 Strava 的训练日志,以包含以下所有训练特征:

  • 会话(或一周)的平均配速(分钟/公里)、距离和持续时间。

  • Strava 的 相对努力痛苦)得分,用于评估整体训练强度或每周强度。

  • 每个心率区间的时间显示了训练时间如何分配在轻松、中等和艰难的努力之间。Strava 使用 5 个 HR 区间(Z1, …, Z5),这些区间对应于逐渐增强的努力,并基于跑者的心率占其最大心率的比例。

HR 区间数据对跑者很有用,因为它提供了细化的努力/强度度量,并帮助跑者区分轻松和更努力的训练。如上所述,这对跟踪训练进展非常有用。此外,强度和努力也有助于跑者跟踪恢复跑步,以便他们能够以所需的 轻松努力 完成,并为本周晚些时候的更艰难训练做好准备。实际上,跑者经常被鼓励采用 80/20 方法 进行训练——80%的训练应以 轻松 努力(HR 区域 1 和 2)进行——以防止过度训练和潜在伤害。

访问 Strava 数据

本文的重点是 Strava 训练数据的可视化,因此不会详细讨论如何从 Strava 收集这些数据。只需说明 Strava 提供了一个 API,可以在获得用户许可的情况下获得授权访问你的数据或其他用户的数据。我使用了这个 API 来访问我的数据,并且网上有几篇文章——这里或 这里,例如——感兴趣的读者可以了解如何自己进行操作。

一个使用 Strava API 收集的每日会话数据样本。

上述是我从 Strava API 收集的活动数据的一个子集。每一行对应一个单独的活动,包括活动日期、距离()、持续时间()、相对努力(痛苦评分)以及在不同心率区间内的跑步距离等信息(在心率区间内花费的时间等)。

训练会话饼图

我们的首要任务是升级当前 Strava 训练日志中单次训练活动的简单可视化;见下文。它显示了会话的名称(用户提供的或默认的 Strava 名称)和完成的距离,但没有任何配速或其他强度相关的信息。

单次训练活动(42.4km),对应今年的都柏林马拉松。

下面的图表显示了我们对同一活动的替代建议。这个新图表由几个不同的组件(标题、头部、图表、脚部)组成,以便更容易定位其不同的信息元素,而无需依赖绝对位置坐标;顺便说一句,这些元素周围的边框只是为了突出这些元素,最终可视化中不会使用这些边框。以这种方式使用单独的元素将通过使调整这些图表的大小更容易,并避免不同信息元素之间的碰撞,从而促进以后的网格布局。这些元素包括会话距离和平均配速(脚部),而这次饼图的大小与会话的总时长成比例,这也在标题中指明(190 分钟),以及自上次会话(22 小时)以来的经过(休息)时间。

对于单个会话/活动的建议可视化,显示了在每个心率区间花费的时间,以及会话的相对努力、距离、平均配速、总跑步时间以及自上次会话(休息)以来的时间等。

重要的是,与使用简单圆圈来表示会话覆盖的距离不同,饼图用于通过 HR 区间编码重要的强度信息。这些扇区按顺时针方向排列,从“中午”位置开始,按照 HR 区间 (Z1, Z2, …, Z5) 的顺序排列,扇区的大小对应于在该区间内花费的时间比例。扇区的颜色也表示 HR 区间,并与稍后讨论的每周条形图中使用的颜色匹配。在这项活动中,跑步主要发生在 Z2 和 Z3 区间,也有一些时间花在 Z4 区间。

最终,活动的总体相对努力 (RE) 分数显示在饼图的中心,背景颜色与其相对于训练块的值成比例。在这种情况下,深红色背景表明相对努力值为 362 是训练块中最高的;实际上,这是最高的。

显然,这种新的可视化提供了比 Strava 更显著的信息,但在屏幕空间上没有显著增加,并且在强调哪些信息时具有更大的灵活性。例如,上述饼图的总体大小基于整体会话时间(此示例中为 190 分钟),但可以根据运动员的需求进行配置。例如,可以使用总体距离,如 Strava 训练日志中的情况,或相对努力或功率(对于骑自行车的人)或运动员的感知努力,如果可用。如果需要,也可以用配速或功率区间代替 HR 区间。对于感兴趣的读者,本文末尾提供了重建此图表版本的 Python 示例代码。

训练周总结条形图

我们需要的第二种图表总结了一整周或训练。这在默认的 Strava 训练日志中几乎不存在,除了每行旁边提供的每周总距离。

我们希望添加有关每周在每个 HR 区间中所花时间的相关信息,以及配速和相对努力信息。我们需要以与新的饼图视觉效果兼容的方式进行,以便这两种类型的图表可以在我们的新训练日志可视化中一起使用。

新的每周总结图表如下所示,展示了比赛日还有 10 周的都柏林马拉松训练的一周。在那一周内跟踪了 238 分钟的跑步(46.88 公里)(共 4 次),平均配速为 5:40 分钟/公里。每周相对努力较高(RE = 365),大约 53%的训练是在轻松的努力下进行的(Z1 和 Z2;125/238)。条形图显示了每个 HR 区间的每周分钟数,颜色编码与会话饼图中使用的方案匹配。

2023 年 8 月 14 日至 20 日的一周的示例每周训练总结图表,距比赛日还有 10 周。

这个图表的风格和结构(标题、标题、图表、页脚)与会议饼图兼容——尺寸、位置、颜色等——这样它们可以在大型图表网格中一起使用。再次强调,根据需要很容易替换不同类型的训练数据,例如配速或功率区间,样本 Python 代码在文章末尾提供给感兴趣的读者以重新创建此图表。

设计训练日志网格

现在我们可以为每个会话构建饼图和每周条形图,是时候将这些图表汇总成一个多周可视化了。就像 Strava 训练日志一样,我们将使用网格布局,每一行对应一个训练周,每一列对应一天;见下图。最左边的列将用于提供每周总结。因此,对于一个 16 周的马拉松训练计划,我们将需要一个具有 16 行(每周一个)和 8 列(每周总结加 7 天)的网格。

简单的子图网格。

使用 Matplotlib 生成这样的网格非常简单。例如,下面的代码片段就可以完成这个任务,从而可以根据周和天来生成和定位各个图表。

简单的网格布局代码。

然而,这种方法不适用于我们需要的可视化类型,因为每个可视化组件(会议饼图或周总结)由多个独立组件(标题、页眉、图表、页脚)组成。相反,我们需要一个网格,其外观更像下面的示例,每个组件作为一个单独的轴/子图。

更复杂的子图网格,以支持训练日志可视化。

为了生成这种类型的网格,我们可以使用 Matplotlib 强大的gridspec,并使用add_subplot将各个元素(标题、图表、页脚等)分配到网格中的适当位置。深入探讨 Matplotlib 和gridspec的内容超出了本文的范围,但下面展示的网格设置代码说明了总体方法。简而言之,主网格中的 16 行每行分配 10 个单位的高度(row_h)(第 5 行)。然后,每个图表的标题、页眉和页脚部分分配 1 个单位的高度,而图表本身分配 6 个单位的高度。最后,我们为每行添加一个 gutter(1 个单位的高度),以控制行之间的间距。感兴趣的读者可以在这里了解更多。

复杂的网格布局代码。

没有什么能阻止显示比这里讨论的 16 周更多或更少的训练周。例如,大多数马拉松训练计划涵盖 12 到 20 周的训练,而在我们最终的可视化中,我们将展示 12 周的训练。

完成训练日志可视化

将所有这些内容整合起来,产生了下面的大型可视化。在这个案例中,我们展示了 12 周的都柏林马拉松训练,每一行对应一个训练周。第一列显示了每周的总结,其余 7 列显示了每天的活动。没有活动的天数标记为休息日。

作者对 2023 年都柏林马拉松的 16 周训练周期。

这是一种复杂的可视化——可能需要一个大屏幕才能舒适地查看——但它比 Strava 的默认训练日志捕捉了更多有用的训练信息。它也有助于更深入的探讨和分析。

比如,我们可以看到,我的大部分努力都是在周三进行的;周三的饼图显示了在 Z3 区间花费的时间明显多于周二和周四的轻松/恢复训练。同样,我在周六的长跑也表现出较高的强度,不仅仅因为距离,还因为这些跑步通常包含了按马拉松配速要求进行的更高强度的阶段,通常在跑步的最后阶段;这些长跑通常会在周日后跟较短的恢复跑。周六还包括了在第 5、7 和 10 周的几场比赛,这也解释了为什么这些天在 Z4 区间花费的时间比其他长跑要多。我们还可以看到,在最后两周的恢复阶段,跑步量下降,而强度保持不变,因为轻松跑被赛前的休息日取代。

最后,值得注意的是,有时跑者会每天跟踪多项活动。例如,一些跑者会进行早晨和晚上的活动,而另一些跑者则会将一个单独的训练分成几个部分,以涵盖单独的热身、主要活动和放松活动。目前,我们将一天中的所有活动合并为一个综合活动。例如,在第 5 周的周六,以上的可视化显示我参加了都柏林半程马拉松(都柏林马拉松系列赛中的一场年度比赛),但当天的数据显示为 30.2 公里的跑步,而不是 21.1 公里的半程马拉松距离。原因是这 30.2 公里包括了单独的热身和放松活动。当然,与其以这种方式汇总活动,我们可以决定实施不同的政策,例如在多项活动的日子里,特别是比赛日,重点关注最长(或最快)的活动。

结论

本文旨在探索如何开发一个更具信息性的训练日志,使用 Strava 的默认训练日志作为起点。最终的可视化捕捉了大量额外的有用信息,特别是关于训练强度和努力程度,这使得评估训练进展变得更为容易。

我们已经描述了如何使用 Python 和 Matplotlib 构建单独的活动和总结图表(下面提供了示例代码),并讨论了如何将这些图表组装成一个复杂但灵活的网格结构。

最后,值得强调的是,这种方法可以很容易地适应其他类型的运动,基于这些运动更相关的信息。例如,如上所述,骑行者可能希望在训练日志中包括功率区间而不是心率区间。实际上,随着休闲运动员变得更加仪器化,通过新的可穿戴传感器,开发者将越来越需要找到新颖的方式来呈现这些新形式的数据,以支持运动员的训练和比赛。

注意:作者制作了所有的图像和代码。

示例代码

绘制会话图表

以下代码示例展示了创建会话饼图的方法。本文假设所需的会话数据(距离、时间、强度等)已经以 Pandas 系列session的形式提供,无需进一步解释。

绘制每周总结图表

以下代码示例展示了创建每周总结条形图的方法。它期望相关的每周会话数据作为数据框week提供。