{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 图结构\n", "\n", "参考:[图结构](https://daobook.github.io/plotly-book/tutorial/fundamentals/00_figure-structure.html) & [renderers](https://daobook.github.io/plotly-book/tutorial/fundamentals/02_renderers.html)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import plotly.express as px\n", "from plotly import graph_objects as go\n", "\n", "go.FigureWidget(); # 初始化" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 图的属性\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "先看简单的折线图:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "hovertemplate": "x=%{x}
y=%{y}", "legendgroup": "", "line": { "color": "#636efa", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "", "orientation": "v", "showlegend": false, "type": "scatter", "x": [ "a", "b", "c" ], "xaxis": "x", "y": [ 1, 3, 2 ], "yaxis": "y" } ], "layout": { "legend": { "tracegroupgap": 0 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "sequentialminus": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "样例图" }, "xaxis": { "anchor": "y", "domain": [ 0, 1 ], "title": { "text": "x" } }, "yaxis": { "anchor": "x", "domain": [ 0, 1 ], "title": { "text": "y" } } } }, "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = px.line(x=[\"a\", \"b\", \"c\"], \n", " y=[1, 3, 2], title=\"样例图\")\n", "fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Figure` 存在三个顶级属性:{data}`data`、{data}`layout` 以及 {data}`frames`。\n", "\n", "### `data`\n", "\n", "`data` 的值必须是称为“轨迹”(“traces”)的字典列表。\n", "\n", "* 每个轨迹可能是超过 40 种类型中的一种(见下面按子图类型组织的列表,包括例如 [Scatter Plots](https://daobook.github.io/plotly-book/tutorial/basic-charts/line-and-scatter.html#plotly-basic-charts-line-and-scatter)、[Bar Charts](https://daobook.github.io/plotly-book/tutorial/basic-charts/bar-charts.html#plotly-basic-charts-bar-charts)、[Pie Charts](https://daobook.github.io/plotly-book/tutorial/basic-charts/pie-charts.html#plotly-basic-charts-pie-charts)、[3D Surface Plots](https://daobook.github.io/plotly-book/tutorial/3d-charts/3d-surface-plots.html#plotly-3d-charts-3d-surface-plots)、[Choropleth Maps](https://daobook.github.io/plotly-book/tutorial/maps/choropleth-maps.html#plotly-maps-choropleth-maps),并表示一组相关的图形标记。每个轨迹必须有一个 `type` 属性,该属性定义其他被允许的属性。\n", "\n", "* 每个轨迹都绘制在一个 [Subplots](https://daobook.github.io/plotly-book/tutorial/fundamentals/16_subplots.html#plotly-subplots) 上,该子图的类型必须与轨迹的类型兼容,或者是它自己的子图(参见下面)。\n", "\n", "* 轨迹可能只有一个 [Legends](https://daobook.github.io/plotly-book/tutorial/fundamentals/14_legend.html#plotly-legend) 项,但饼图和漏斗区域轨迹(funnelarea traces)除外(见下文)。\n", "\n", "* 某些轨迹类型支持 [带有关联颜色条的连续颜色](https://daobook.github.io/plotly-book/tutorial/fundamentals/20_colorscales.html#plotly-colorscales),当使用 `coloraxis` 属性时,可以通过轨迹内的属性或布局内的属性来控制颜色条。\n", "\n", "### `layout`\n", "\n", "图的三个顶级属性中的第二个是 `layout`,它的值在文本中称为\"布局\",必须是一个字典,包含控制图中非数据相关部分的定位和配置的属性,例如:\n", "\n", "* 尺寸和边距,定义了“纸张坐标”的边界\n", "\n", "* 图的默认值:[模板](https://daobook.github.io/plotly-book/tutorial/fundamentals/06_templates.html#plotly-templates)、[字体、标题、颜色、悬停标签](https://daobook.github.io/plotly-book/tutorial/fundamentals/12_figure-labels.html#plotly-figure-labels) 和 mobar\n", "\n", "* 可在容器和/或纸坐标中定位 [标题](https://daobook.github.io/plotly-book/tutorial/fundamentals/12_figure-labels.html#plotly-figure-labels) 和 [Legends](https://daobook.github.io/plotly-book/tutorial/fundamentals/14_legend.html#plotly-legend)\n", "\n", "* 可在纸坐标中定位 [标题](https://daobook.github.io/plotly-book/tutorial/fundamentals/12_figure-labels.html#plotly-figure-labels) 和 [颜色轴和相关的颜色条](https://daobook.github.io/plotly-book/tutorial/fundamentals/20_colorscales.html#plotly-colorscales)\n", "\n", "* 各种类型的子图,可在其上绘制多个轨迹,并在纸坐标中定位:\n", "\n", " * `xaxis`, `yaxis`, `xaxis2`, `yaxis3` 等:X 和 Y 笛卡儿轴,它们的交点是笛卡儿子图\n", "\n", " * `scene`, `scene2`, `scene3`等:3D 场景子图\n", "\n", " * `ternary`, `ternary2`, `ternary3`, `polar`, `polar2`, `polar3`, `geo`, `geo2`, `geo3`, `mapbox`, `mapbox2`, `mabox3`等:三元,极坐标,地理或 mapbox 子图\n", "\n", "* 非数据标记,可以在纸坐标中定位,也可以在链接到二维笛卡尔子图的数据坐标中定位\n", "\n", " * `annotations`:[带有或不带有箭头的文本注释](https://daobook.github.io/plotly-book/tutorial/fundamentals/21_text-and-annotations.html#plotly-text-and-annotations)\n", "\n", " * `shapes`:[直线,矩形,椭圆或开放或封闭的路径](https://daobook.github.io/plotly-book/tutorial/fundamentals/24_shapes.html#plotly-shapes)\n", "\n", " * `images`:[背景或装饰图像](https://daobook.github.io/plotly-book/tutorial/fundamentals/23_images.html#plotly-images)\n", "\n", "* 可以在纸坐标中定位的控件,当用户与之交互时,可以触发 Plotly.js 函数\n", "\n", " * `updatemenus`:[自定义按钮](https://daobook.github.io/plotly-book/tutorial/controls/custom-buttons.html#plotly-controls-custom-buttons) 和 [Dropdown Menus](https://daobook.github.io/plotly-book/tutorial/controls/dropdowns.html#plotly-controls-dropdowns)\n", "\n", " * `sliders`:[Sliders](https://daobook.github.io/plotly-book/tutorial/controls/sliders.html#plotly-controls-sliders)\n", "\n", "### `frames`\n", "\n", "图的三个顶级属性中的第三个是 `frames`,它的值必须是一个字典列表,在 [animation plot](https://daobook.github.io/plotly-book/tutorial/animations/index.html) 中定义顺序帧。每个帧包含自己的数据属性和其他参数。动画通常是通过 `layout.sliders` 和/或 `layout.updatemenus` 定义的控件来触发和控制的。\n", "\n", "### 属性设置\n", "\n", "[`plotly.graph_objects` 模块包含自动生成的 Python 类层次结构](https://daobook.github.io/plotly-book/tutorial/fundamentals/34_graph-objects.html#plotly-graph-objects),这些类代表图模式中的非叶子属性,并为它们提供了一个 Python API。当 [操作 `plotly.graph_objects.Figure` 对象](https://daobook.github.io/plotly-book/tutorial/fundamentals/01_creating-and-updating-figures.html#plotly-creating-and-updating-figures) 时,属性可以直接使用 Python 对象属性设置,例如`fig.layout.title.font.family=\"Open Sans\"`或使用 `update` 方法和 [魔法下划线表示法](https://daobook.github.io/plotly-book/tutorial/fundamentals/01_creating-and-updating-figures.html#plotly-magic-underscore-notation),例如 `fig.update_layout(title_font_family=\"Open Sans\")`。\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 坐标系\n", "\n", "在图布局中配置的各种图组件支持名为 `x` 或 `y` 的定位属性,它们的值可以在“纸坐标”(有时称为“绘图分数”(“plot fractions”)或“标准化坐标”(“normalized coordinates”))中指定。例如,包含 `layout.xaxis.domain` 或 `layout.legend.x` 或 `layout.annotation[].x`。\n", "\n", "在纸坐标中定位不是绝对像素,而是相对于原点 $(0, 0)$ 在 `(layout.margin.l, layout.margin.b)`,且 $(1, 1)$ 在 `(layout.width-layout.margin.r, layout.height-layout.margin.t)` 处定义的(注:`layout.margin` 是像素值,`layout.width` 也是)。允许纸张坐标值小于 $0$ 或大于 $1$,指示 plot 边缘的区域。\n", "\n", "要在“纸”坐标中定位对象,相应的轴参考系被设置为 `\"paper\"`。例如,形状的 `xref` 属性将被设置为 `\"paper\"`,因此形状的 `x` 值指的是它在纸坐标中的位置。\n", "\n", "请注意 `layout.margin` 属性的内容,默认情况下是根据某些项(如标题或图例)的位置和尺寸计算的,当将 `layout.xaxis.autommargin` 属性设置为 `True` 时,也可以根据 `tick` 标签的位置和尺寸计算。这将自动增加边界值,从而缩小 $(0, 0)$ 和 $(1, 1)$ 点之间定义的物理区域。将某些项定位于小于 $0$ 或大于 $1$ 的纸坐标也会触发此行为。然而,`layout.width` 和 `layout.height` 被认为是既定的,所以这个图永远不会因其内容而增加或减少。\n", "\n", "图形标题可以使用“容器坐标”来定位,容器坐标 $(0,0)$ 和 $(1,1)$ 分别锚定在图形的左下和右上,因此与 `layout.margin` 的值无关。\n", "\n", "此外,形状、注释和图像可以相对于轴的域放置,例如,`x` 值为 $0.5$ 将把对象放置在 `x` 轴的中间位置,而不管 `layout.xaxis.domain` 属性中指定的域是什么。可以通过在对象的 `axis` 引用属性中向 `axis` 引用添加 `'domain'` 来指定此行为。例如,为形状设置 `yref = 'y2 domain'` 将引用命名为 `y2` 的轴的长度和位置。" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.10.4 ('tvmx': conda)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.4" }, "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "e579259ee6098e2b9319de590d145b4b096774fe457bdf04260e3ba5c171e887" } } }, "nbformat": 4, "nbformat_minor": 2 }