xarray-plotly 0.0.3__tar.gz → 0.0.5__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.3 → xarray_plotly-0.0.5}/.github/workflows/ci.yml +3 -3
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/.github/workflows/docs.yml +2 -2
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/.github/workflows/release.yml +2 -2
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/PKG-INFO +11 -11
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/README.md +2 -2
- xarray_plotly-0.0.5/docs/examples/datasets.ipynb +261 -0
- xarray_plotly-0.0.5/docs/examples/dimensions.ipynb +232 -0
- xarray_plotly-0.0.5/docs/examples/figure.ipynb +236 -0
- xarray_plotly-0.0.5/docs/examples/kwargs.ipynb +251 -0
- xarray_plotly-0.0.5/docs/examples/plot-types.ipynb +170 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/docs/index.md +2 -1
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/mkdocs.yml +4 -1
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/pyproject.toml +8 -8
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/tests/test_accessor.py +89 -3
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/xarray_plotly/__init__.py +36 -9
- xarray_plotly-0.0.5/xarray_plotly/accessor.py +604 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/xarray_plotly/config.py +13 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/xarray_plotly/plotting.py +61 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/xarray_plotly.egg-info/PKG-INFO +11 -11
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/xarray_plotly.egg-info/SOURCES.txt +4 -1
- xarray_plotly-0.0.5/xarray_plotly.egg-info/requires.txt +19 -0
- xarray_plotly-0.0.3/docs/examples/advanced.ipynb +0 -320
- xarray_plotly-0.0.3/docs/examples/plot-types.ipynb +0 -382
- xarray_plotly-0.0.3/xarray_plotly/accessor.py +0 -275
- xarray_plotly-0.0.3/xarray_plotly.egg-info/requires.txt +0 -19
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/.github/dependabot.yml +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/.github/workflows/dependabot-auto-merge.yml +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/.gitignore +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/.pre-commit-config.yaml +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/CONTRIBUTING.md +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/LICENSE +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/docs/api.md +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/docs/getting-started.ipynb +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/setup.cfg +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/tests/__init__.py +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/tests/test_common.py +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/tests/test_config.py +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/xarray_plotly/common.py +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/xarray_plotly/py.typed +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/xarray_plotly.egg-info/dependency_links.txt +0 -0
- {xarray_plotly-0.0.3 → xarray_plotly-0.0.5}/xarray_plotly.egg-info/top_level.txt +0 -0
|
@@ -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 }}
|
|
@@ -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.5
|
|
4
4
|
Summary: Interactive Plotly Express plotting accessor for xarray
|
|
5
5
|
Author: Felix
|
|
6
6
|
License: MIT
|
|
@@ -25,16 +25,16 @@ 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==1.
|
|
31
|
-
Requires-Dist: ruff==0.
|
|
32
|
-
Requires-Dist: pre-commit==4.
|
|
33
|
-
Requires-Dist: nbstripout==0.8.
|
|
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
35
|
Requires-Dist: mkdocs==1.6.1; extra == "docs"
|
|
36
|
-
Requires-Dist: mkdocs-material==9.
|
|
37
|
-
Requires-Dist: mkdocstrings[python]==0.
|
|
36
|
+
Requires-Dist: mkdocs-material==9.7.1; extra == "docs"
|
|
37
|
+
Requires-Dist: mkdocstrings[python]==1.0.0; extra == "docs"
|
|
38
38
|
Requires-Dist: mkdocs-jupyter==0.25.1; extra == "docs"
|
|
39
39
|
Requires-Dist: mkdocs-plotly-plugin==0.1.3; extra == "docs"
|
|
40
40
|
Requires-Dist: jupyter==1.1.1; extra == "docs"
|
|
@@ -44,8 +44,8 @@ Dynamic: license-file
|
|
|
44
44
|
|
|
45
45
|
**Interactive Plotly Express plotting for xarray**
|
|
46
46
|
|
|
47
|
-
[](https://badge.fury.io/py/xarray-plotly)
|
|
48
|
+
[](https://pypi.org/project/xarray-plotly/)
|
|
49
49
|
[](https://github.com/FBumann/xarray_plotly/actions)
|
|
50
50
|
[](https://fbumann.github.io/xarray_plotly/)
|
|
51
51
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**Interactive Plotly Express plotting for xarray**
|
|
4
4
|
|
|
5
|
-
[](https://badge.fury.io/py/xarray-plotly)
|
|
6
|
+
[](https://pypi.org/project/xarray-plotly/)
|
|
7
7
|
[](https://github.com/FBumann/xarray_plotly/actions)
|
|
8
8
|
[](https://fbumann.github.io/xarray_plotly/)
|
|
9
9
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# Dataset Plotting\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"Plot multiple variables from an xarray Dataset with automatic or custom slot assignment."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"cell_type": "code",
|
|
14
|
+
"execution_count": null,
|
|
15
|
+
"metadata": {},
|
|
16
|
+
"outputs": [],
|
|
17
|
+
"source": [
|
|
18
|
+
"import numpy as np\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
|
+
"# Create a Dataset with multiple variables\n",
|
|
33
|
+
"time = np.arange(50)\n",
|
|
34
|
+
"cities = [\"NYC\", \"LA\", \"Chicago\"]\n",
|
|
35
|
+
"\n",
|
|
36
|
+
"ds = xr.Dataset(\n",
|
|
37
|
+
" {\n",
|
|
38
|
+
" \"temperature\": ([\"time\", \"city\"], 20 + 5 * np.random.randn(50, 3).cumsum(axis=0) / 10),\n",
|
|
39
|
+
" \"humidity\": ([\"time\", \"city\"], 50 + 10 * np.random.randn(50, 3).cumsum(axis=0) / 10),\n",
|
|
40
|
+
" \"pressure\": ([\"time\", \"city\"], 1013 + np.random.randn(50, 3).cumsum(axis=0)),\n",
|
|
41
|
+
" },\n",
|
|
42
|
+
" coords={\"time\": time, \"city\": cities},\n",
|
|
43
|
+
")\n",
|
|
44
|
+
"ds"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"cell_type": "markdown",
|
|
49
|
+
"metadata": {},
|
|
50
|
+
"source": [
|
|
51
|
+
"## Plot All Variables\n",
|
|
52
|
+
"\n",
|
|
53
|
+
"When you call a plot method on a Dataset without specifying `var`, all variables are combined into a single DataArray with a new `\"variable\"` dimension:"
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"cell_type": "code",
|
|
58
|
+
"execution_count": null,
|
|
59
|
+
"metadata": {},
|
|
60
|
+
"outputs": [],
|
|
61
|
+
"source": [
|
|
62
|
+
"# All variables: time -> x, variable -> color, city -> line_dash\n",
|
|
63
|
+
"xpx(ds).line()"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"cell_type": "markdown",
|
|
68
|
+
"metadata": {},
|
|
69
|
+
"source": [
|
|
70
|
+
"## Control Where \"variable\" Goes\n",
|
|
71
|
+
"\n",
|
|
72
|
+
"The `\"variable\"` dimension can be assigned to any slot:"
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"cell_type": "code",
|
|
77
|
+
"execution_count": null,
|
|
78
|
+
"metadata": {},
|
|
79
|
+
"outputs": [],
|
|
80
|
+
"source": [
|
|
81
|
+
"# Variables as facet columns\n",
|
|
82
|
+
"xpx(ds).line(facet_col=\"variable\")"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"cell_type": "code",
|
|
87
|
+
"execution_count": null,
|
|
88
|
+
"metadata": {},
|
|
89
|
+
"outputs": [],
|
|
90
|
+
"source": [
|
|
91
|
+
"# Variables as rows, cities as columns\n",
|
|
92
|
+
"xpx(ds).line(facet_row=\"variable\", facet_col=\"city\")"
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"cell_type": "markdown",
|
|
97
|
+
"metadata": {},
|
|
98
|
+
"source": [
|
|
99
|
+
"## Configure Default \"variable\" Position\n",
|
|
100
|
+
"\n",
|
|
101
|
+
"By default, `\"variable\"` is placed as the **second** dimension so it maps to `color`. This keeps your first dimension (e.g., time) on the x-axis.\n",
|
|
102
|
+
"\n",
|
|
103
|
+
"You can change this globally with `config.set_options()`:"
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"cell_type": "code",
|
|
108
|
+
"execution_count": null,
|
|
109
|
+
"metadata": {},
|
|
110
|
+
"outputs": [],
|
|
111
|
+
"source": [
|
|
112
|
+
"# Default: position=1 (second) -> variable goes to color\n",
|
|
113
|
+
"# Note: to_array() puts \"variable\" first, but xpx() reorders it to position 1\n",
|
|
114
|
+
"print(\"Raw to_array() dims:\", ds.to_array().dims) # (variable, time, city)\n",
|
|
115
|
+
"print(\"After xpx reorder: (time, variable, city)\") # time->x, variable->color\n",
|
|
116
|
+
"xpx(ds).line(title=\"Default: variable as color (position=1)\")"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"cell_type": "code",
|
|
121
|
+
"execution_count": null,
|
|
122
|
+
"metadata": {},
|
|
123
|
+
"outputs": [],
|
|
124
|
+
"source": [
|
|
125
|
+
"# Position 0: variable goes first (x-axis) - usually not what you want!\n",
|
|
126
|
+
"with config.set_options(dataset_variable_position=0):\n",
|
|
127
|
+
" fig = xpx(ds).line(title=\"position=0: variable on x-axis (probably not desired)\")\n",
|
|
128
|
+
"fig"
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"cell_type": "code",
|
|
133
|
+
"execution_count": null,
|
|
134
|
+
"metadata": {},
|
|
135
|
+
"outputs": [],
|
|
136
|
+
"source": [
|
|
137
|
+
"# Position -1: variable goes last -> city gets color, variable gets line_dash\n",
|
|
138
|
+
"with config.set_options(dataset_variable_position=-1):\n",
|
|
139
|
+
" fig = xpx(ds).line(title=\"position=-1: variable as line_dash\")\n",
|
|
140
|
+
"fig"
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"cell_type": "markdown",
|
|
145
|
+
"metadata": {},
|
|
146
|
+
"source": [
|
|
147
|
+
"## Plot a Single Variable\n",
|
|
148
|
+
"\n",
|
|
149
|
+
"Use `var=\"name\"` to plot just one variable:"
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"cell_type": "code",
|
|
154
|
+
"execution_count": null,
|
|
155
|
+
"metadata": {},
|
|
156
|
+
"outputs": [],
|
|
157
|
+
"source": [
|
|
158
|
+
"xpx(ds).line(var=\"temperature\", title=\"Temperature Only\")"
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"cell_type": "markdown",
|
|
163
|
+
"metadata": {},
|
|
164
|
+
"source": [
|
|
165
|
+
"## Different Plot Types"
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"cell_type": "code",
|
|
170
|
+
"execution_count": null,
|
|
171
|
+
"metadata": {},
|
|
172
|
+
"outputs": [],
|
|
173
|
+
"source": [
|
|
174
|
+
"# Bar chart - latest values by city\n",
|
|
175
|
+
"xpx(ds.isel(time=-1)).bar(x=\"city\", color=\"variable\", barmode=\"group\")"
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"cell_type": "code",
|
|
180
|
+
"execution_count": null,
|
|
181
|
+
"metadata": {},
|
|
182
|
+
"outputs": [],
|
|
183
|
+
"source": [
|
|
184
|
+
"# Box plot - distribution by variable\n",
|
|
185
|
+
"xpx(ds).box(x=\"variable\", color=\"city\")"
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"cell_type": "code",
|
|
190
|
+
"execution_count": null,
|
|
191
|
+
"metadata": {},
|
|
192
|
+
"outputs": [],
|
|
193
|
+
"source": [
|
|
194
|
+
"# Area chart\n",
|
|
195
|
+
"xpx(ds).area(var=\"humidity\", title=\"Humidity Over Time\")"
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"cell_type": "code",
|
|
200
|
+
"execution_count": null,
|
|
201
|
+
"metadata": {},
|
|
202
|
+
"outputs": [],
|
|
203
|
+
"source": [
|
|
204
|
+
"# Scatter\n",
|
|
205
|
+
"xpx(ds).scatter(var=\"temperature\", title=\"Temperature Scatter\")"
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"cell_type": "code",
|
|
210
|
+
"execution_count": null,
|
|
211
|
+
"metadata": {},
|
|
212
|
+
"outputs": [],
|
|
213
|
+
"source": [
|
|
214
|
+
"# Pie chart - snapshot at one time\n",
|
|
215
|
+
"xpx(ds.isel(time=-1)).pie(var=\"temperature\", names=\"city\", title=\"Temperature Distribution\")"
|
|
216
|
+
]
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"cell_type": "markdown",
|
|
220
|
+
"metadata": {},
|
|
221
|
+
"source": [
|
|
222
|
+
"## Combining Slot Assignments\n",
|
|
223
|
+
"\n",
|
|
224
|
+
"Mix explicit assignments with auto-assignment:"
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"cell_type": "code",
|
|
229
|
+
"execution_count": null,
|
|
230
|
+
"metadata": {},
|
|
231
|
+
"outputs": [],
|
|
232
|
+
"source": [
|
|
233
|
+
"# Explicit: variable -> facet_col, let city auto-assign to color\n",
|
|
234
|
+
"xpx(ds).line(facet_col=\"variable\", color=\"city\")"
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"cell_type": "code",
|
|
239
|
+
"execution_count": null,
|
|
240
|
+
"metadata": {},
|
|
241
|
+
"outputs": [],
|
|
242
|
+
"source": [
|
|
243
|
+
"# Skip color slot with None\n",
|
|
244
|
+
"xpx(ds).line(var=\"temperature\", color=None)"
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
],
|
|
248
|
+
"metadata": {
|
|
249
|
+
"kernelspec": {
|
|
250
|
+
"display_name": "Python 3",
|
|
251
|
+
"language": "python",
|
|
252
|
+
"name": "python3"
|
|
253
|
+
},
|
|
254
|
+
"language_info": {
|
|
255
|
+
"name": "python",
|
|
256
|
+
"version": "3.12.0"
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
"nbformat": 4,
|
|
260
|
+
"nbformat_minor": 4
|
|
261
|
+
}
|
|
@@ -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
|
+
}
|