xarray-plotly 0.0.2__tar.gz → 0.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- xarray_plotly-0.0.4/.github/dependabot.yml +25 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/.github/workflows/ci.yml +3 -3
- xarray_plotly-0.0.4/.github/workflows/dependabot-auto-merge.yml +24 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/.github/workflows/docs.yml +2 -2
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/.github/workflows/release.yml +2 -2
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/PKG-INFO +17 -12
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/README.md +4 -0
- xarray_plotly-0.0.4/docs/examples/dimensions.ipynb +232 -0
- xarray_plotly-0.0.4/docs/examples/figure.ipynb +236 -0
- xarray_plotly-0.0.4/docs/examples/kwargs.ipynb +251 -0
- xarray_plotly-0.0.4/docs/examples/plot-types.ipynb +170 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/docs/getting-started.ipynb +30 -34
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/docs/index.md +2 -1
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/mkdocs.yml +3 -1
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/pyproject.toml +12 -11
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/tests/test_accessor.py +89 -3
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/xarray_plotly/__init__.py +36 -9
- xarray_plotly-0.0.4/xarray_plotly/accessor.py +586 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/xarray_plotly/config.py +1 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/xarray_plotly/plotting.py +61 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/xarray_plotly.egg-info/PKG-INFO +17 -12
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/xarray_plotly.egg-info/SOURCES.txt +5 -1
- xarray_plotly-0.0.4/xarray_plotly.egg-info/requires.txt +19 -0
- xarray_plotly-0.0.2/docs/examples/advanced.ipynb +0 -425
- xarray_plotly-0.0.2/docs/examples/plot-types.ipynb +0 -381
- xarray_plotly-0.0.2/xarray_plotly/accessor.py +0 -275
- xarray_plotly-0.0.2/xarray_plotly.egg-info/requires.txt +0 -18
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/.gitignore +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/.pre-commit-config.yaml +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/CONTRIBUTING.md +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/LICENSE +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/docs/api.md +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/setup.cfg +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/tests/__init__.py +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/tests/test_common.py +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/tests/test_config.py +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/xarray_plotly/common.py +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/xarray_plotly/py.typed +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/xarray_plotly.egg-info/dependency_links.txt +0 -0
- {xarray_plotly-0.0.2 → xarray_plotly-0.0.4}/xarray_plotly.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
groups:
|
|
8
|
+
dev-dependencies:
|
|
9
|
+
patterns:
|
|
10
|
+
- "pytest*"
|
|
11
|
+
- "mypy"
|
|
12
|
+
- "ruff"
|
|
13
|
+
- "pre-commit"
|
|
14
|
+
- "nbstripout"
|
|
15
|
+
docs-dependencies:
|
|
16
|
+
patterns:
|
|
17
|
+
- "mkdocs*"
|
|
18
|
+
- "pooch"
|
|
19
|
+
- "netcdf4"
|
|
20
|
+
- "jupyter"
|
|
21
|
+
|
|
22
|
+
- package-ecosystem: "github-actions"
|
|
23
|
+
directory: "/"
|
|
24
|
+
schedule:
|
|
25
|
+
interval: "weekly"
|
|
@@ -14,10 +14,10 @@ jobs:
|
|
|
14
14
|
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
15
|
|
|
16
16
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
18
|
|
|
19
19
|
- name: Install uv
|
|
20
|
-
uses: astral-sh/setup-uv@
|
|
20
|
+
uses: astral-sh/setup-uv@v7
|
|
21
21
|
|
|
22
22
|
- name: Set up Python ${{ matrix.python-version }}
|
|
23
23
|
run: uv python install ${{ matrix.python-version }}
|
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
run: uv run pytest --cov=xarray_plotly --cov-report=xml
|
|
36
36
|
|
|
37
37
|
- name: Upload coverage
|
|
38
|
-
uses: codecov/codecov-action@
|
|
38
|
+
uses: codecov/codecov-action@v5
|
|
39
39
|
if: matrix.python-version == '3.12'
|
|
40
40
|
with:
|
|
41
41
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Dependabot auto-merge
|
|
2
|
+
on: pull_request
|
|
3
|
+
|
|
4
|
+
permissions:
|
|
5
|
+
contents: write
|
|
6
|
+
pull-requests: write
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
dependabot:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
if: github.actor == 'dependabot[bot]'
|
|
12
|
+
steps:
|
|
13
|
+
- name: Dependabot metadata
|
|
14
|
+
id: metadata
|
|
15
|
+
uses: dependabot/fetch-metadata@v2
|
|
16
|
+
with:
|
|
17
|
+
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
18
|
+
|
|
19
|
+
- name: Auto-merge minor and patch updates
|
|
20
|
+
if: steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor'
|
|
21
|
+
run: gh pr merge --auto --squash "$PR_URL"
|
|
22
|
+
env:
|
|
23
|
+
PR_URL: ${{ github.event.pull_request.html_url }}
|
|
24
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -14,10 +14,10 @@ jobs:
|
|
|
14
14
|
runs-on: ubuntu-latest
|
|
15
15
|
|
|
16
16
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
18
|
|
|
19
19
|
- name: Install uv
|
|
20
|
-
uses: astral-sh/setup-uv@
|
|
20
|
+
uses: astral-sh/setup-uv@v7
|
|
21
21
|
|
|
22
22
|
- name: Install dependencies
|
|
23
23
|
run: uv sync --extra docs
|
|
@@ -13,10 +13,10 @@ jobs:
|
|
|
13
13
|
contents: write # for creating GitHub release
|
|
14
14
|
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
17
|
|
|
18
18
|
- name: Install uv
|
|
19
|
-
uses: astral-sh/setup-uv@
|
|
19
|
+
uses: astral-sh/setup-uv@v7
|
|
20
20
|
|
|
21
21
|
- name: Build package
|
|
22
22
|
run: uv build
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xarray_plotly
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: Interactive Plotly Express plotting accessor for xarray
|
|
5
5
|
Author: Felix
|
|
6
6
|
License: MIT
|
|
@@ -25,18 +25,19 @@ Requires-Dist: xarray>=2023.1.0
|
|
|
25
25
|
Requires-Dist: plotly>=5.0.0
|
|
26
26
|
Requires-Dist: pandas>=1.5.0
|
|
27
27
|
Provides-Extra: dev
|
|
28
|
-
Requires-Dist: pytest
|
|
29
|
-
Requires-Dist: pytest-cov
|
|
30
|
-
Requires-Dist: mypy
|
|
31
|
-
Requires-Dist: ruff
|
|
32
|
-
Requires-Dist: pre-commit
|
|
33
|
-
Requires-Dist: nbstripout
|
|
28
|
+
Requires-Dist: pytest==9.0.2; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-cov==7.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: mypy==1.19.1; extra == "dev"
|
|
31
|
+
Requires-Dist: ruff==0.14.11; extra == "dev"
|
|
32
|
+
Requires-Dist: pre-commit==4.5.1; extra == "dev"
|
|
33
|
+
Requires-Dist: nbstripout==0.8.2; extra == "dev"
|
|
34
34
|
Provides-Extra: docs
|
|
35
|
-
Requires-Dist: mkdocs
|
|
36
|
-
Requires-Dist: mkdocs-material
|
|
37
|
-
Requires-Dist: mkdocstrings[python]
|
|
38
|
-
Requires-Dist: mkdocs-jupyter
|
|
39
|
-
Requires-Dist: mkdocs-plotly-plugin
|
|
35
|
+
Requires-Dist: mkdocs==1.6.1; extra == "docs"
|
|
36
|
+
Requires-Dist: mkdocs-material==9.7.1; extra == "docs"
|
|
37
|
+
Requires-Dist: mkdocstrings[python]==1.0.0; extra == "docs"
|
|
38
|
+
Requires-Dist: mkdocs-jupyter==0.25.1; extra == "docs"
|
|
39
|
+
Requires-Dist: mkdocs-plotly-plugin==0.1.3; extra == "docs"
|
|
40
|
+
Requires-Dist: jupyter==1.1.1; extra == "docs"
|
|
40
41
|
Dynamic: license-file
|
|
41
42
|
|
|
42
43
|
# xarray_plotly
|
|
@@ -45,7 +46,9 @@ Dynamic: license-file
|
|
|
45
46
|
|
|
46
47
|
[](https://badge.fury.io/py/xarray_plotly)
|
|
47
48
|
[](https://pypi.org/project/xarray_plotly/)
|
|
49
|
+
[](https://github.com/FBumann/xarray_plotly/actions)
|
|
48
50
|
[](https://fbumann.github.io/xarray_plotly/)
|
|
51
|
+
[](https://opensource.org/licenses/MIT)
|
|
49
52
|
|
|
50
53
|
## Installation
|
|
51
54
|
|
|
@@ -75,6 +78,8 @@ from xarray_plotly import xpx
|
|
|
75
78
|
fig = xpx(da).line()
|
|
76
79
|
```
|
|
77
80
|
|
|
81
|
+
**Why `xpx()`?** The accessor (`da.plotly`) works but IDEs can't provide code completion for it. This is because xarray accessors are registered dynamically at runtime, making them invisible to static type checkers. The `xpx()` function provides the same functionality with full IDE support. This limitation could only be solved by xarray itself, if at all — it may be a fundamental Python limitation.
|
|
82
|
+
|
|
78
83
|
## Documentation
|
|
79
84
|
|
|
80
85
|
Full documentation: [https://fbumann.github.io/xarray_plotly](https://fbumann.github.io/xarray_plotly)
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://badge.fury.io/py/xarray_plotly)
|
|
6
6
|
[](https://pypi.org/project/xarray_plotly/)
|
|
7
|
+
[](https://github.com/FBumann/xarray_plotly/actions)
|
|
7
8
|
[](https://fbumann.github.io/xarray_plotly/)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
10
|
|
|
9
11
|
## Installation
|
|
10
12
|
|
|
@@ -34,6 +36,8 @@ from xarray_plotly import xpx
|
|
|
34
36
|
fig = xpx(da).line()
|
|
35
37
|
```
|
|
36
38
|
|
|
39
|
+
**Why `xpx()`?** The accessor (`da.plotly`) works but IDEs can't provide code completion for it. This is because xarray accessors are registered dynamically at runtime, making them invisible to static type checkers. The `xpx()` function provides the same functionality with full IDE support. This limitation could only be solved by xarray itself, if at all — it may be a fundamental Python limitation.
|
|
40
|
+
|
|
37
41
|
## Documentation
|
|
38
42
|
|
|
39
43
|
Full documentation: [https://fbumann.github.io/xarray_plotly](https://fbumann.github.io/xarray_plotly)
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# Dimensions, Facets & Animation\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"How to control which dimensions map to which visual properties."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"cell_type": "code",
|
|
14
|
+
"execution_count": null,
|
|
15
|
+
"metadata": {},
|
|
16
|
+
"outputs": [],
|
|
17
|
+
"source": [
|
|
18
|
+
"import plotly.express as px\n",
|
|
19
|
+
"import xarray as xr\n",
|
|
20
|
+
"\n",
|
|
21
|
+
"from xarray_plotly import config, xpx\n",
|
|
22
|
+
"\n",
|
|
23
|
+
"config.notebook()"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"cell_type": "code",
|
|
28
|
+
"execution_count": null,
|
|
29
|
+
"metadata": {},
|
|
30
|
+
"outputs": [],
|
|
31
|
+
"source": [
|
|
32
|
+
"# Sample data: 2D\n",
|
|
33
|
+
"df = px.data.stocks().set_index(\"date\")\n",
|
|
34
|
+
"df.index = df.index.astype(\"datetime64[ns]\")\n",
|
|
35
|
+
"\n",
|
|
36
|
+
"stocks = xr.DataArray(\n",
|
|
37
|
+
" df.values,\n",
|
|
38
|
+
" dims=[\"date\", \"company\"],\n",
|
|
39
|
+
" coords={\"date\": df.index, \"company\": df.columns.tolist()},\n",
|
|
40
|
+
" name=\"price\",\n",
|
|
41
|
+
")\n",
|
|
42
|
+
"\n",
|
|
43
|
+
"# Sample data: 3D\n",
|
|
44
|
+
"df_gap = px.data.gapminder()\n",
|
|
45
|
+
"countries = [\"United States\", \"China\", \"Germany\", \"Brazil\"]\n",
|
|
46
|
+
"metrics = [\"lifeExp\", \"gdpPercap\"]\n",
|
|
47
|
+
"\n",
|
|
48
|
+
"arrays = []\n",
|
|
49
|
+
"for metric in metrics:\n",
|
|
50
|
+
" df_pivot = df_gap[df_gap[\"country\"].isin(countries)].pivot(\n",
|
|
51
|
+
" index=\"year\", columns=\"country\", values=metric\n",
|
|
52
|
+
" )\n",
|
|
53
|
+
" arrays.append(df_pivot.values)\n",
|
|
54
|
+
"\n",
|
|
55
|
+
"data_3d = xr.DataArray(\n",
|
|
56
|
+
" arrays,\n",
|
|
57
|
+
" dims=[\"metric\", \"year\", \"country\"],\n",
|
|
58
|
+
" coords={\n",
|
|
59
|
+
" \"metric\": metrics,\n",
|
|
60
|
+
" \"year\": df_pivot.index.tolist(),\n",
|
|
61
|
+
" \"country\": df_pivot.columns.tolist(),\n",
|
|
62
|
+
" },\n",
|
|
63
|
+
" name=\"value\",\n",
|
|
64
|
+
")"
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"cell_type": "markdown",
|
|
69
|
+
"metadata": {},
|
|
70
|
+
"source": [
|
|
71
|
+
"## Default Dimension Assignment\n",
|
|
72
|
+
"\n",
|
|
73
|
+
"Dimensions are assigned to slots in order:"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"cell_type": "code",
|
|
78
|
+
"execution_count": null,
|
|
79
|
+
"metadata": {},
|
|
80
|
+
"outputs": [],
|
|
81
|
+
"source": [
|
|
82
|
+
"# date → x, company → color\n",
|
|
83
|
+
"xpx(stocks).line()"
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"cell_type": "markdown",
|
|
88
|
+
"metadata": {},
|
|
89
|
+
"source": [
|
|
90
|
+
"## Explicit Assignment\n",
|
|
91
|
+
"\n",
|
|
92
|
+
"Override the defaults by specifying which dimension goes where:"
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"cell_type": "code",
|
|
97
|
+
"execution_count": null,
|
|
98
|
+
"metadata": {},
|
|
99
|
+
"outputs": [],
|
|
100
|
+
"source": [
|
|
101
|
+
"# Swap: company → x, date → color\n",
|
|
102
|
+
"xpx(stocks.isel(date=[0, 50, 100])).bar(x=\"company\", color=\"date\")"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"cell_type": "markdown",
|
|
107
|
+
"metadata": {},
|
|
108
|
+
"source": [
|
|
109
|
+
"## Skipping Slots with None\n",
|
|
110
|
+
"\n",
|
|
111
|
+
"Use `None` to skip a slot, so dimensions shift to the next available slot:"
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"cell_type": "code",
|
|
116
|
+
"execution_count": null,
|
|
117
|
+
"metadata": {},
|
|
118
|
+
"outputs": [],
|
|
119
|
+
"source": [
|
|
120
|
+
"# Skip color → company goes to line_dash instead\n",
|
|
121
|
+
"xpx(stocks.sel(company=[\"GOOG\", \"AAPL\", \"MSFT\"])).line(color=None)"
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"cell_type": "markdown",
|
|
126
|
+
"metadata": {},
|
|
127
|
+
"source": [
|
|
128
|
+
"## Available Slots\n",
|
|
129
|
+
"\n",
|
|
130
|
+
"Different plot types have different slots:\n",
|
|
131
|
+
"\n",
|
|
132
|
+
"| Plot | Slots (in order) |\n",
|
|
133
|
+
"|------|------------------|\n",
|
|
134
|
+
"| line | x, color, line_dash, facet_col, facet_row, animation_frame |\n",
|
|
135
|
+
"| scatter | x, color, symbol, facet_col, facet_row, animation_frame |\n",
|
|
136
|
+
"| bar | x, color, facet_col, facet_row, animation_frame |\n",
|
|
137
|
+
"| imshow | x, y, facet_col, facet_row, animation_frame |"
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"cell_type": "code",
|
|
142
|
+
"execution_count": null,
|
|
143
|
+
"metadata": {},
|
|
144
|
+
"outputs": [],
|
|
145
|
+
"source": [
|
|
146
|
+
"# line_dash for third dimension\n",
|
|
147
|
+
"xpx(stocks.sel(company=[\"GOOG\", \"AAPL\"])).line(line_dash=\"company\")"
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"cell_type": "code",
|
|
152
|
+
"execution_count": null,
|
|
153
|
+
"metadata": {},
|
|
154
|
+
"outputs": [],
|
|
155
|
+
"source": [
|
|
156
|
+
"# symbol for scatter\n",
|
|
157
|
+
"xpx(stocks.sel(company=[\"GOOG\", \"AAPL\"])).scatter(symbol=\"company\")"
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"cell_type": "markdown",
|
|
162
|
+
"metadata": {},
|
|
163
|
+
"source": [
|
|
164
|
+
"## Faceting\n",
|
|
165
|
+
"\n",
|
|
166
|
+
"Create a grid of subplots with `facet_col` and `facet_row`:"
|
|
167
|
+
]
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"cell_type": "code",
|
|
171
|
+
"execution_count": null,
|
|
172
|
+
"metadata": {},
|
|
173
|
+
"outputs": [],
|
|
174
|
+
"source": [
|
|
175
|
+
"# One subplot per metric\n",
|
|
176
|
+
"xpx(data_3d).line(facet_col=\"metric\")"
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"cell_type": "code",
|
|
181
|
+
"execution_count": null,
|
|
182
|
+
"metadata": {},
|
|
183
|
+
"outputs": [],
|
|
184
|
+
"source": [
|
|
185
|
+
"# Grid: metric x country\n",
|
|
186
|
+
"xpx(data_3d).line(x=\"year\", facet_col=\"metric\", facet_row=\"country\")"
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"cell_type": "markdown",
|
|
191
|
+
"metadata": {},
|
|
192
|
+
"source": [
|
|
193
|
+
"## Animation\n",
|
|
194
|
+
"\n",
|
|
195
|
+
"Animate over a dimension with `animation_frame`:"
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"cell_type": "code",
|
|
200
|
+
"execution_count": null,
|
|
201
|
+
"metadata": {},
|
|
202
|
+
"outputs": [],
|
|
203
|
+
"source": [
|
|
204
|
+
"# Animate through years\n",
|
|
205
|
+
"xpx(data_3d.sel(metric=\"lifeExp\")).bar(x=\"country\", animation_frame=\"year\")"
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"cell_type": "code",
|
|
210
|
+
"execution_count": null,
|
|
211
|
+
"metadata": {},
|
|
212
|
+
"outputs": [],
|
|
213
|
+
"source": [
|
|
214
|
+
"# Animate heatmap\n",
|
|
215
|
+
"xpx(data_3d).imshow(animation_frame=\"metric\")"
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
"metadata": {
|
|
220
|
+
"kernelspec": {
|
|
221
|
+
"display_name": "Python 3",
|
|
222
|
+
"language": "python",
|
|
223
|
+
"name": "python3"
|
|
224
|
+
},
|
|
225
|
+
"language_info": {
|
|
226
|
+
"name": "python",
|
|
227
|
+
"version": "3.12.0"
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
"nbformat": 4,
|
|
231
|
+
"nbformat_minor": 4
|
|
232
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# Working with Figures\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"All methods return a [Plotly Figure](https://plotly.com/python/figure-structure/) that can be modified and exported."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"cell_type": "code",
|
|
14
|
+
"execution_count": null,
|
|
15
|
+
"metadata": {},
|
|
16
|
+
"outputs": [],
|
|
17
|
+
"source": [
|
|
18
|
+
"import plotly.express as px\n",
|
|
19
|
+
"import plotly.graph_objects as go\n",
|
|
20
|
+
"import xarray as xr\n",
|
|
21
|
+
"\n",
|
|
22
|
+
"from xarray_plotly import config, xpx\n",
|
|
23
|
+
"\n",
|
|
24
|
+
"config.notebook()"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"cell_type": "code",
|
|
29
|
+
"execution_count": null,
|
|
30
|
+
"metadata": {},
|
|
31
|
+
"outputs": [],
|
|
32
|
+
"source": [
|
|
33
|
+
"df = px.data.stocks().set_index(\"date\")\n",
|
|
34
|
+
"df.index = df.index.astype(\"datetime64[ns]\")\n",
|
|
35
|
+
"\n",
|
|
36
|
+
"stocks = xr.DataArray(\n",
|
|
37
|
+
" df.values,\n",
|
|
38
|
+
" dims=[\"date\", \"company\"],\n",
|
|
39
|
+
" coords={\"date\": df.index, \"company\": df.columns.tolist()},\n",
|
|
40
|
+
" name=\"price\",\n",
|
|
41
|
+
")"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"cell_type": "markdown",
|
|
46
|
+
"metadata": {},
|
|
47
|
+
"source": [
|
|
48
|
+
"## update_layout\n",
|
|
49
|
+
"\n",
|
|
50
|
+
"Modify [layout properties](https://plotly.com/python/reference/layout/): title, legend, margins, fonts."
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"cell_type": "code",
|
|
55
|
+
"execution_count": null,
|
|
56
|
+
"metadata": {},
|
|
57
|
+
"outputs": [],
|
|
58
|
+
"source": [
|
|
59
|
+
"fig = xpx(stocks).line()\n",
|
|
60
|
+
"fig.update_layout(\n",
|
|
61
|
+
" title={\"text\": \"Stock Prices\", \"x\": 0.5},\n",
|
|
62
|
+
" legend={\"orientation\": \"h\", \"y\": 1.02},\n",
|
|
63
|
+
")\n",
|
|
64
|
+
"fig"
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"cell_type": "markdown",
|
|
69
|
+
"metadata": {},
|
|
70
|
+
"source": [
|
|
71
|
+
"## update_traces\n",
|
|
72
|
+
"\n",
|
|
73
|
+
"Modify [trace properties](https://plotly.com/python/reference/): line width, markers, opacity."
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"cell_type": "code",
|
|
78
|
+
"execution_count": null,
|
|
79
|
+
"metadata": {},
|
|
80
|
+
"outputs": [],
|
|
81
|
+
"source": [
|
|
82
|
+
"fig = xpx(stocks).line()\n",
|
|
83
|
+
"fig.update_traces(line={\"width\": 3})\n",
|
|
84
|
+
"fig"
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"cell_type": "code",
|
|
89
|
+
"execution_count": null,
|
|
90
|
+
"metadata": {},
|
|
91
|
+
"outputs": [],
|
|
92
|
+
"source": [
|
|
93
|
+
"fig = xpx(stocks).scatter()\n",
|
|
94
|
+
"fig.update_traces(marker={\"size\": 10, \"opacity\": 0.7})\n",
|
|
95
|
+
"fig"
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"cell_type": "markdown",
|
|
100
|
+
"metadata": {},
|
|
101
|
+
"source": [
|
|
102
|
+
"## update_xaxes / update_yaxes\n",
|
|
103
|
+
"\n",
|
|
104
|
+
"Modify [axis properties](https://plotly.com/python/axes/)."
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"cell_type": "code",
|
|
109
|
+
"execution_count": null,
|
|
110
|
+
"metadata": {},
|
|
111
|
+
"outputs": [],
|
|
112
|
+
"source": [
|
|
113
|
+
"fig = xpx(stocks).line()\n",
|
|
114
|
+
"fig.update_xaxes(rangeslider_visible=True)\n",
|
|
115
|
+
"fig.update_yaxes(tickformat=\".0%\")\n",
|
|
116
|
+
"fig"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"cell_type": "markdown",
|
|
121
|
+
"metadata": {},
|
|
122
|
+
"source": [
|
|
123
|
+
"## add_hline / add_vline\n",
|
|
124
|
+
"\n",
|
|
125
|
+
"Add reference lines. See [shapes](https://plotly.com/python/shapes/)."
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"cell_type": "code",
|
|
130
|
+
"execution_count": null,
|
|
131
|
+
"metadata": {},
|
|
132
|
+
"outputs": [],
|
|
133
|
+
"source": [
|
|
134
|
+
"fig = xpx(stocks).line()\n",
|
|
135
|
+
"fig.add_hline(y=1.0, line_dash=\"dash\", line_color=\"gray\", annotation_text=\"Baseline\")\n",
|
|
136
|
+
"fig.add_vline(x=\"2018-10-01\", line_dash=\"dot\", line_color=\"red\")\n",
|
|
137
|
+
"fig"
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"cell_type": "markdown",
|
|
142
|
+
"metadata": {},
|
|
143
|
+
"source": [
|
|
144
|
+
"## add_annotation\n",
|
|
145
|
+
"\n",
|
|
146
|
+
"Add text annotations. See [annotations](https://plotly.com/python/text-and-annotations/)."
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"cell_type": "code",
|
|
151
|
+
"execution_count": null,
|
|
152
|
+
"metadata": {},
|
|
153
|
+
"outputs": [],
|
|
154
|
+
"source": [
|
|
155
|
+
"fig = xpx(stocks).line()\n",
|
|
156
|
+
"fig.add_annotation(x=\"2018-10-01\", y=1.4, text=\"Peak\", showarrow=True, arrowhead=2)\n",
|
|
157
|
+
"fig"
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"cell_type": "markdown",
|
|
162
|
+
"metadata": {},
|
|
163
|
+
"source": [
|
|
164
|
+
"## add_trace\n",
|
|
165
|
+
"\n",
|
|
166
|
+
"Add custom traces using [Graph Objects](https://plotly.com/python/graph-objects/)."
|
|
167
|
+
]
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"cell_type": "code",
|
|
171
|
+
"execution_count": null,
|
|
172
|
+
"metadata": {},
|
|
173
|
+
"outputs": [],
|
|
174
|
+
"source": [
|
|
175
|
+
"fig = xpx(stocks.sel(company=\"GOOG\")).line()\n",
|
|
176
|
+
"\n",
|
|
177
|
+
"# Add moving average\n",
|
|
178
|
+
"goog = stocks.sel(company=\"GOOG\")\n",
|
|
179
|
+
"ma = goog.rolling(date=20, center=True).mean()\n",
|
|
180
|
+
"\n",
|
|
181
|
+
"fig.add_trace(\n",
|
|
182
|
+
" go.Scatter(\n",
|
|
183
|
+
" x=ma.coords[\"date\"].values,\n",
|
|
184
|
+
" y=ma.values,\n",
|
|
185
|
+
" mode=\"lines\",\n",
|
|
186
|
+
" name=\"20-day MA\",\n",
|
|
187
|
+
" line={\"dash\": \"dash\", \"color\": \"red\"},\n",
|
|
188
|
+
" )\n",
|
|
189
|
+
")\n",
|
|
190
|
+
"fig"
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"cell_type": "markdown",
|
|
195
|
+
"metadata": {},
|
|
196
|
+
"source": [
|
|
197
|
+
"## Export\n",
|
|
198
|
+
"\n",
|
|
199
|
+
"### HTML\n",
|
|
200
|
+
"\n",
|
|
201
|
+
"See [HTML export](https://plotly.com/python/interactive-html-export/).\n",
|
|
202
|
+
"\n",
|
|
203
|
+
"```python\n",
|
|
204
|
+
"fig.write_html(\"plot.html\")\n",
|
|
205
|
+
"fig.write_html(\"plot.html\", include_plotlyjs=\"cdn\") # smaller file\n",
|
|
206
|
+
"```\n",
|
|
207
|
+
"\n",
|
|
208
|
+
"### Images\n",
|
|
209
|
+
"\n",
|
|
210
|
+
"Requires [kaleido](https://github.com/plotly/Kaleido): `pip install kaleido`\n",
|
|
211
|
+
"\n",
|
|
212
|
+
"See [static image export](https://plotly.com/python/static-image-export/).\n",
|
|
213
|
+
"\n",
|
|
214
|
+
"```python\n",
|
|
215
|
+
"fig.write_image(\"plot.png\")\n",
|
|
216
|
+
"fig.write_image(\"plot.png\", scale=2) # higher resolution\n",
|
|
217
|
+
"fig.write_image(\"plot.svg\")\n",
|
|
218
|
+
"fig.write_image(\"plot.pdf\")\n",
|
|
219
|
+
"```"
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
],
|
|
223
|
+
"metadata": {
|
|
224
|
+
"kernelspec": {
|
|
225
|
+
"display_name": "Python 3",
|
|
226
|
+
"language": "python",
|
|
227
|
+
"name": "python3"
|
|
228
|
+
},
|
|
229
|
+
"language_info": {
|
|
230
|
+
"name": "python",
|
|
231
|
+
"version": "3.12.0"
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
"nbformat": 4,
|
|
235
|
+
"nbformat_minor": 4
|
|
236
|
+
}
|