Altair:可调整大小的多面图表

Altair: resizable faceted chart

我需要一个可调整大小的分面图表,但 width="container" 指的是各个分面。我能想出的最好的办法是一些自定义 HTML,但它并不能正常工作。

rand = np.random.RandomState(0)
data = pd.DataFrame\
    ( rand.randint(100,500,(15,2))
    , index=[*["a"]*5,*["b"]*5,*["c"]*5]
    , columns=["x","y"]
    ).rename_axis("k").reset_index()
chart1 =\
    ( alt.Chart(data)
    . mark_point()
    . encode(x="x",y="y",color="k",shape="k",size="k")
    )

chart2 =\
    ( alt.Chart(data)
    . transform_regression
        ( on="x"
        , regression="y"
        , groupby=["k"]
        , method="poly"
        )
    . mark_line()
    . encode(x="x",y="y",color="k")
    )

chart =\
    ( (chart1 + chart2)
    . properties(height=300, width="container")
    . facet(column="k:N")
    . interactive()
    )

stats.chart_embed\
    ( chart
    , filename="TEMP.html"
    , container=container
    , style=style
    )
container="""<div class="test"><div class="vega-vis"></div></div>"""

style = """
body {
  white-space: nowrap;
}
.vega-vis {
  width: 100%;
}
.test {
  width: 32%;
}
...
"""

应该做更多的研究。已经有一些 Whosebug 问题。最好描述使用 javascript 设置宽度。我不确定您是否可以通过 addResizeListener 连接到 Vega 的调整大小机制而不触发另一个调整大小;必须注意避免无限循环。或者您可以禁用自动调整大小,通过 ResizeObserver 连接到容器的调整大小事件并通过 view.width().run().

触发图表调整大小
  • vega-lite: how to set responsive width using facet?

一个开放的 Vega 问题,有许多解决方法,例如编辑 Vega JSON。我想象一个 JSON-PATCH 到 vegaEmbed 通过 opt.patch。但是,当更新 width 信号时,补丁可能会被覆盖。

还有 Vega 公关草案:

最后,您可以修改HTML。一个完美的版本:

chart =\
    ( (chart1 + chart2)
    . properties
        ( height=300
        , width="container"
        )
    . facet(column="k:N")
    . properties
        ( autosize=alt.AutoSizeParams
            ( type="fit"
            # The resize parameter is the only required parameter, but I
            # included the others in case you have a more complicated chart.
            , resize=True
            , contains="padding"
            )
        )
    . interactive()
    )
<div class="vega-vis"></div>
.vega-vis {
  width: 100%;
}
.chart-wrapper {
  /* Normally 'chart-wrapper' is the size of its 'vega-vis' container minus
   * the padding for the button. The size of 'chart-wrapper' determines the
   * size of the canvas/plot. So you want 'chart-wrapper' to be 1/3 of the
   * container minus the padding.
  */
  width: calc(33% - var(--vega-action-padding,38px));
}

这种方法有一些缺点。对于数据非常密集的图表,通过 autosize 参数启用调整大小会大大降低页面速度。并且不可能调整垂直连接图表的大小,因此当一个图表被分面时,每个图表都是相同的宽度。此外,在将图表调整为容器的宽度后,其轴与相邻图表垂直对齐。由于多面图表在容器计算中不包括图例和填充,这会强制相邻图表超过容器宽度,所有图表均如此。有必要通过 JavaScript 绕过图表的内部结构来设置每个连接图表的宽度 - 这不是一件容易的事。