使用Seaborn FacetGrid绘制时间序列图

9
我有一个DataFrame(data),它具有简单的整数索引和5列。这些列是Date,Country,AgeGroup,Gender和Stat。(名称已更改以保护无辜者。)我想生成一个FacetGrid,其中Country定义行,AgeGroup定义列,Gender定义hue。对于这些特定内容,我想生成一个时间序列图表。也就是说,我应该得到一个图表数组,每个图表上都有2个时间序列(1个男性,1个女性)。我可以通过以下方式非常接近:
g = sns.FacetGrid(data, row='Country', col='AgeGroup', hue='Gender')
g.map(plt.plot, 'Stat')

然而,这只是在x轴上给了我样本编号,而不是日期。在这种情况下,是否有快速解决方法。
更一般地说,我了解使用FacetGrid的方法是制作网格,然后将绘图函数map到网格上。如果我想要编写自己的绘图函数,它需要遵循哪些约定?特别地,我如何编写自己的绘图函数(传递给FacetGridmap)来接受我的数据集中多列数据?

当你说“这只是在x轴上给我样本编号而不是日期”,并不清楚日期应该从哪里来。这是你的数据框中的另一列吗? - mwaskom
是的,请看上面,有一列叫做“日期”,我想使用它来生成有意义的x轴刻度。 - 8one6
1个回答

10

首先回答您的一般问题。您可以传递给 FacetGrid.map 的函数规则如下:

  • 它们必须将类似数组的输入作为位置参数,第一个参数对应 x 轴,第二个参数对应 y 轴(稍后关于第二个条件有更多说明)
  • 它们还必须接受两个关键字参数:colorlabel。如果要使用 hue 变量,则这些应该被传递到底层绘图函数,尽管如果与您正在制作的特定图形无关,则可以仅捕获 **kwargs 并不做任何操作。
  • 调用时,它们必须在“当前活动”的 matplotlib Axes 上绘制图形。

可能有些情况下,您的函数绘制出看起来正确的图形,但并没有采取 xy 位置输入。我认为这基本上是您使用 plt.plot 的方式所发生的情况。然后可以更容易地调用例如 g.set_axis_labels("Date", "Stat"),这样可以适当地重命名轴。您可能还想执行 g.set(xticklabels=dates) 以获取更有意义的刻度。

还有一个更一般的函数 FacetGrid.map_dataframe。这里的规则类似,但是您传递的函数必须在名为 data 的参数中接受 dataframe 输入,并且它不采用类似数组的位置输入,而是采用与该 dataframe 中的变量对应的字符串。在通过各个面孔进行迭代时,将使用输入数据框的掩码调用该函数,该掩码仅用于该组合的 rowcolhue 级别的值。

因此,在您的特定情况下,您需要编写一个我们可以称为 plot_by_date 的函数,其应该类似于以下内容:

def plot_by_date(x, y, color=None, label=None):

    ...

(我在正文方面可能更有帮助,但实际上我不太知道如何处理日期和matplotlib). 最终结果是,当您调用此函数时,它应该绘制在当前激活的Axes上。然后执行

g.map(plot_by_date, "Date", "Stat")

我想它应该可以工作。


1
我的意思是,如果我想自己编写一个函数,它应该返回什么?比如说,我想创建一个愚蠢的函数,在每个面上只画一条在y=2处的水平线,并忽略所有输入数据。那么这个函数会是什么样子? - 8one6
2
啊,返回值被忽略了...重要的是函数绘图。实际上,对于这个特定的例子,你可以只做 g.map(plt.axhline, y=2)。不确定这是否有助于您的一般理解。 - mwaskom
1
我会稍微尝试一下。我已经进入了一个避免“仅仅绘图”的状态,而更喜欢像ax.plotdf.plot(ax=ax)这样的方式来明确指定艺术家的工作位置。所以这对我来说有点“违反常规”。但我会尝试一下。 - 8one6
4
这可能会有所帮助:http://nbviewer.ipython.org/gist/mwaskom/9276378379d757fe0cc6 - mwaskom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接