使用Seaborn FacetGrid绘制时间序列
我有一个数据表(data
),它有一个简单的整数索引和5列。列的名称分别是 Date
(日期)、Country
(国家)、AgeGroup
(年龄组)、Gender
(性别)和 Stat
(统计数据)。为了保护隐私,名字都换了。我想制作一个 FacetGrid
,其中 Country
用来定义行,AgeGroup
用来定义列,而 Gender
则用来定义颜色。对于这些特定的内容,我想生成一个时间序列图。也就是说,我应该得到一组图表,每个图表上有两条时间序列(1条男性,1条女性)。我已经接近实现这个目标:
g = sns.FacetGrid(data, row='Country', col='AgeGroup', hue='Gender')
g.map(plt.plot, 'Stat')
不过,这样做只是在x轴上显示样本数量,而不是日期。有没有什么快速的解决办法呢?
更一般来说,我知道使用 FacetGrid
的方法是先创建网格,然后将一个绘图函数映射到它上面。如果我想自己写一个绘图函数,它需要遵循什么样的规则呢?特别是,我该如何编写自己的绘图函数(以便传递给 map
用于 FacetGrid
),使其能够接受来自数据集的多列数据呢?
1 个回答
我先来回答你更一般的问题。你可以传给 FacetGrid.map
的函数有几个规则:
- 这些函数必须接受类似数组的输入作为位置参数,第一个参数对应 x 轴,第二个参数对应 y 轴(不过,关于第二个条件我稍后会详细说)。
- 它们还必须接受两个关键字参数:
color
和label
。如果你想使用一个hue
变量,那么这些参数应该传给底层的绘图函数,不过如果这些参数对你正在制作的特定图表不相关,你可以选择接收**kwargs
但不做任何处理。 - 当被调用时,它们必须在“当前活动”的 matplotlib Axes 上绘制图表。
可能会有一些情况,你的函数绘制的图表看起来是正确的,但并没有接受 x
、y
这样的输入。我觉得这就是你使用 plt.plot
时的情况。这样的话,使用 map
后,直接调用 g.set_axis_labels("Date", "Stat")
来正确命名你的坐标轴会更简单。你可能还想用 g.set(xticklabels=dates)
来获得更有意义的刻度。
还有一个更通用的函数,叫 FacetGrid.map_dataframe
。这里的规则类似,但你传入的函数必须接受一个名为 data
的数据框输入,而不是接受类似数组的位置输入,而是接受与数据框中变量对应的字符串。在每次遍历这些面板时,函数会被调用,并且输入的数据框只包含该 row
、col
和 hue
组合的值。
所以在你的具体情况下,你需要写一个函数,我们可以称之为 plot_by_date
,它应该看起来像这样:
def plot_by_date(x, y, color=None, label=None):
...
(我在函数的具体内容上可能帮不了你,因为我其实对日期和 matplotlib 的处理不太了解)。最终结果是,当你调用这个函数时,它应该在当前活动的 Axes 上绘制图表。然后执行
g.map(plot_by_date, "Date", "Stat")
我觉得这样应该就能工作了。