Skip to content

Commit f26b29a

Browse files
committed
Merge pull request #527 from clarkfitzg/facet2
faceted plots
2 parents cb600ee + 3247fdb commit f26b29a

File tree

7 files changed

+892
-66
lines changed

7 files changed

+892
-66
lines changed

doc/api-hidden.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,8 @@
147147
ufuncs.tan
148148
ufuncs.tanh
149149
ufuncs.trunc
150+
151+
plot.FacetGrid.map_dataarray
152+
plot.FacetGrid.set_titles
153+
plot.FacetGrid.set_ticks
154+
plot.FacetGrid.map

doc/api.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,5 @@ Plotting
415415
plot.imshow
416416
plot.line
417417
plot.pcolormesh
418+
plot.FacetGrid
419+

doc/plotting.rst

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ Xray's plotting capabilities are centered around
1616
:py:class:`xray.DataArray` objects.
1717
To plot :py:class:`xray.Dataset` objects
1818
simply access the relevant DataArrays, ie ``dset['var1']``.
19+
Here we focus mostly on arrays 2d or larger. If your data fits
20+
nicely into a pandas DataFrame then you're better off using one of the more
21+
developed tools there.
1922

2023
Xray plotting functionality is a thin wrapper around the popular
2124
`matplotlib <http://matplotlib.org/>`_ library.
@@ -51,10 +54,11 @@ The following imports are necessary for all of the examples.
5154
.. ipython:: python
5255
5356
import numpy as np
57+
import pandas as pd
5458
import matplotlib.pyplot as plt
5559
import xray
5660
57-
We'll use the North American air temperature dataset.
61+
For these examples we'll use the North American air temperature dataset.
5862

5963
.. ipython:: python
6064
@@ -306,6 +310,125 @@ since levels are chosen automatically).
306310
air2d.plot(levels=10, cmap='husl')
307311
308312
313+
Faceting
314+
--------
315+
316+
Faceting here refers to splitting an array along one or two dimensions and
317+
plotting each group.
318+
Xray's basic plotting is useful for plotting two dimensional arrays. What
319+
about three or four dimensional arrays? That's where facets become helpful.
320+
321+
Consider the temperature data set. There are 4 observations per day for two
322+
years which makes for 2920 values along the time dimension.
323+
One way to visualize this data is to make a
324+
seperate plot for each time period.
325+
326+
The faceted dimension should not have too many values;
327+
faceting on the time dimension will produce 2920 plots. That's
328+
too much to be helpful. To handle this situation try performing
329+
an operation that reduces the size of the data in some way. For example, we
330+
could compute the average air temperature for each month and reduce the
331+
size of this dimension from 2920 -> 12. A simpler way is
332+
to just take a slice on that dimension.
333+
So let's use a slice to pick 6 times throughout the first year.
334+
335+
.. ipython:: python
336+
337+
t = air.isel(time=slice(0, 365 * 4, 250))
338+
t.coords
339+
340+
Simple Example
341+
~~~~~~~~~~~~~~
342+
343+
TODO - replace with the convenience method from plot
344+
345+
We can use :py:meth:`xray.plot.FacetGrid.map_dataarray` on a DataArray:
346+
347+
.. ipython:: python
348+
349+
g = xray.plot.FacetGrid(t, col='time', col_wrap=3)
350+
351+
@savefig plot_facet_dataarray.png height=12in
352+
g.map_dataarray(xray.plot.imshow, 'lon', 'lat')
353+
354+
FacetGrid Objects
355+
~~~~~~~~~~~~~~~~~
356+
357+
:py:class:`xray.plot.FacetGrid` is used to control the behavior of the
358+
multiple plots.
359+
It borrows an API and code from `Seaborn
360+
<http://stanford.edu/~mwaskom/software/seaborn/tutorial/axis_grids.html>`_.
361+
The structure is contained within the ``axes`` and ``name_dicts``
362+
attributes, both 2d Numpy object arrays.
363+
364+
.. ipython:: python
365+
366+
g.axes
367+
368+
g.name_dicts
369+
370+
It's possible to select the :py:class:`xray.DataArray` corresponding to the FacetGrid
371+
through the ``name_dicts``.
372+
373+
.. ipython:: python
374+
375+
g.data.loc[g.name_dicts[0, 0]]
376+
377+
Here is an example of modifying the axes after they have been plotted.
378+
379+
.. ipython:: python
380+
381+
g = (xray.plot
382+
.FacetGrid(t, col='time', col_wrap=3)
383+
.map_dataarray(xray.plot.imshow, 'lon', 'lat')
384+
)
385+
386+
for i, ax in enumerate(g.axes.flat):
387+
ax.set_title('Air Temperature %d' % i)
388+
389+
bottomright = g.axes[-1, -1]
390+
bottomright.annotate('bottom right', (240, 40))
391+
392+
@savefig plot_facet_iterator.png height=12in
393+
plt.show()
394+
395+
4 dimensional
396+
~~~~~~~~~~~~~~
397+
398+
For 4 dimensional arrays we can use the rows and columns of the grids.
399+
Here we create a 4 dimensional array by taking the original data and adding
400+
a fixed amount. Now we can see how the temperature maps would compare if
401+
one were much hotter.
402+
403+
.. ipython:: python
404+
405+
t2 = t.isel(time=slice(0, 2))
406+
t4d = xray.concat([t2, t2 + 40], pd.Index(['normal', 'hot'], name='fourth_dim'))
407+
# This is a 4d array
408+
t4d.coords
409+
410+
g = xray.plot.FacetGrid(t4d, col='time', row='fourth_dim')
411+
412+
@savefig plot_facet_4d.png height=12in
413+
g.map_dataarray(xray.plot.imshow, 'lon', 'lat')
414+
415+
Other features
416+
~~~~~~~~~~~~~~
417+
418+
Faceted plotting supports other arguments common to xray 2d plots.
419+
420+
.. ipython:: python
421+
422+
hasoutliers = t.isel(time=slice(0, 5)).copy()
423+
hasoutliers[0, 0, 0] = -100
424+
hasoutliers[-1, -1, -1] = 400
425+
426+
g = xray.plot.FacetGrid(hasoutliers, col='time', col_wrap=3)
427+
428+
@savefig plot_facet_robust.png height=12in
429+
g.map_dataarray(xray.plot.contourf, 'lon', 'lat', robust=True, cmap='viridis')
430+
431+
309432
Maps
310433
----
311434

xray/plot/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
from .plot import (plot, line, contourf, contour,
22
hist, imshow, pcolormesh)
3+
4+
from .facetgrid import FacetGrid

0 commit comments

Comments
 (0)