使用DataFrame.plot制作带有子图的图表 - 如何使用ax参数

时间:2017-03-29 05:56:37

标签: python pandas matplotlib plot

我无法绕过轴参数,它包含的内容以及如何使用它来制作子图。

如果有人可以解释以下示例中发生的事情,那真的很感激

fig, axes = plt.subplots(nrows=3, ncols=4, figsize=(15, 10))
for idx, feature in enumerate(df.columns[:-1]):
  df.plot(feature, "cnt", subplots=True, kind="scatter", ax=axes[idx / 4, idx % 4])

以下是数据(UCI Bike sharing dataset): a table with 5 rows of raw data 以下是代码段的输出(功能和最终结果的成对比较): a beautiful chart with subplots

更具体地说,这里是我理解的部分(至少我认为我这样做)

  • plt.subplots返回一个包含图形和轴对象的元组(link
  • enumerate()返回包含要素索引及其名称(link
  • 的元组
  • df.plot使用列名将数据放在图
  • 中的子图上

这是我不明白的地方

  • 轴对象包含什么?同样,基于文档和this答案,我确实知道轴包含"轴,刻度线,线2,文本,多边形等等。"但
    • 我们使用axis [x,y]解决了什么?
    • 为什么在这个例子中作者决定使用[idx / 4,idx%4]作为值?

2 个答案:

答案 0 :(得分:2)

代码中的axes对象是{Nnty} matplotlib Axes个对象的数组。由于对subplots()的调用要求3行和4列,因此数组将为3乘4.像axes[r, c]一样索引到数组中,可以得到与Axes对应的r对象1}}和列c,您可以将该对象作为ax关键字参数传递给绘图方法,以使绘图显示在该轴上。例如。如果你想在第二行和第二列中绘制一些内容,你可以调用plot(..., ax=axes[1,1])

代码使用[idx / 4, idx % 4]作为将索引(数字从0到11)转换为3乘4网格中的位置的方法。尝试自己评估该表达式,并将idx依次设置为0到11之间的每个值,然后您就会看到它是如何工作的。

答案 1 :(得分:2)

关于数组索引为[idx / 4, idx % 4]的最后一个问题:

我们的想法是同时遍历所有子图和所有数据框列。问题是轴阵列是二维的,而列阵列是一维的。因此,需要确定循环中的哪一个并将循环索引/ indize映射到另一个维度。

直观的方法是使用两个循环

for i in range(axes.shape[0]):
    for j in range(axes.shape[1]):
        df.plot(df.columns[i*axes.shape[0]+j], "cnt", ... , ax=axes[i,j])

此处,i*axes.shape[0]+j将numpy数组的两个维度映射到列列表的单个维度。

在问题的例子中,循环遍及列,这意味着我们必须以某种方式将一维索引映射到两个维度。这是 [idx / 4, idx % 4] 所做的或应该做的事情。 它只能在python 2中使用。为了使其更易于理解和版本保存,实际上应该使用[idx // 4, idx % 4]//清楚地表明使用整数除法。因此对于前4个idx值(0,1,2,3),idx // 4为0,对于下一组4个值,它为1,依此类推。 idx % 4计算索引模4.所以(0,1,2,3)映射到(0,1,2,3),然后(4,5,6,7)映射到(0 ,1,2,3)再次等。

使用单个循环的替代解决方案是展平轴阵列:

for idx, feature in enumerate(df.columns[:-1]):
    df.plot(feature, "cnt", ... , ax=axes.flatten()[idx])

或者大多数pythonic

for ax, feature in zip(axes.flatten(), df.columns[:-1]):
    df.plot(feature, "cnt", ... , ax=ax)