{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Xarray with Dask Arrays\n", "\n", "\"Xarray\n", " \n", "**[Xarray](http://xarray.pydata.org/en/stable/)** is an open source project and Python package that extends the labeled data functionality of [Pandas](https://pandas.pydata.org/) to N-dimensional array-like datasets. It shares a similar API to [NumPy](http://www.numpy.org/) and [Pandas](https://pandas.pydata.org/) and supports both [Dask](https://dask.org/) and [NumPy](http://www.numpy.org/) arrays under the hood." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:14.990388Z", "iopub.status.busy": "2022-07-27T19:14:14.990139Z", "iopub.status.idle": "2022-07-27T19:14:16.610557Z", "shell.execute_reply": "2022-07-27T19:14:16.609763Z" } }, "outputs": [], "source": [ "%matplotlib inline\n", "\n", "from dask.distributed import Client\n", "import xarray as xr" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Start Dask Client for Dashboard\n", "\n", "Starting the Dask Client is optional. It will provide a dashboard which \n", "is useful to gain insight on the computation. \n", "\n", "The link to the dashboard will become visible when you create the client below. We recommend having it open on one side of your screen while using your notebook on the other side. This can take some effort to arrange your windows, but seeing them both at the same is very useful when learning." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:16.615961Z", "iopub.status.busy": "2022-07-27T19:14:16.615121Z", "iopub.status.idle": "2022-07-27T19:14:18.159546Z", "shell.execute_reply": "2022-07-27T19:14:18.159000Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
\n", "
\n", "

Client

\n", "

Client-4eea680b-0de0-11ed-9d1a-000d3a8f7959

\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "
Connection method: Cluster objectCluster type: distributed.LocalCluster
\n", " Dashboard: http://127.0.0.1:8787/status\n", "
\n", "\n", " \n", "
\n", "

Cluster Info

\n", "
\n", "
\n", "
\n", "
\n", "

LocalCluster

\n", "

8c9bb588

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", " \n", "
\n", " Dashboard: http://127.0.0.1:8787/status\n", " \n", " Workers: 2\n", "
\n", " Total threads: 4\n", " \n", " Total memory: 1.86 GiB\n", "
Status: runningUsing processes: True
\n", "\n", "
\n", " \n", "

Scheduler Info

\n", "
\n", "\n", "
\n", "
\n", "
\n", "
\n", "

Scheduler

\n", "

Scheduler-f26c7784-2ac7-471c-91ac-1b0f9e3135b1

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
\n", " Comm: tcp://127.0.0.1:36327\n", " \n", " Workers: 2\n", "
\n", " Dashboard: http://127.0.0.1:8787/status\n", " \n", " Total threads: 4\n", "
\n", " Started: Just now\n", " \n", " Total memory: 1.86 GiB\n", "
\n", "
\n", "
\n", "\n", "
\n", " \n", "

Workers

\n", "
\n", "\n", " \n", "
\n", "
\n", "
\n", "
\n", " \n", "

Worker: 0

\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", "
\n", " Comm: tcp://127.0.0.1:34819\n", " \n", " Total threads: 2\n", "
\n", " Dashboard: http://127.0.0.1:39963/status\n", " \n", " Memory: 0.93 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:38683\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/dask-worker-space/worker-kg42o2xu\n", "
\n", "
\n", "
\n", "
\n", " \n", "
\n", "
\n", "
\n", "
\n", " \n", "

Worker: 1

\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", "
\n", " Comm: tcp://127.0.0.1:39355\n", " \n", " Total threads: 2\n", "
\n", " Dashboard: http://127.0.0.1:43051/status\n", " \n", " Memory: 0.93 GiB\n", "
\n", " Nanny: tcp://127.0.0.1:43647\n", "
\n", " Local directory: /home/runner/work/dask-examples/dask-examples/dask-worker-space/worker-q4dslyjg\n", "
\n", "
\n", "
\n", "
\n", " \n", "\n", "
\n", "
\n", "\n", "
\n", "
\n", "
\n", "
\n", " \n", "\n", "
\n", "
" ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "client = Client(n_workers=2, threads_per_worker=2, memory_limit='1GB')\n", "client" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Open a sample dataset\n", "\n", "We will use some of xarray's tutorial data for this example. By specifying the chunk shape, xarray will automatically create Dask arrays for each data variable in the `Dataset`. In xarray, `Datasets` are dict-like container of labeled arrays, analogous to the `pandas.DataFrame`. Note that we're taking advantage of xarray's dimension labels when specifying chunk shapes." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:18.162948Z", "iopub.status.busy": "2022-07-27T19:14:18.162479Z", "iopub.status.idle": "2022-07-27T19:14:18.703131Z", "shell.execute_reply": "2022-07-27T19:14:18.701890Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset>\n",
       "Dimensions:  (lat: 25, time: 2920, lon: 53)\n",
       "Coordinates:\n",
       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n",
       "  * time     (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n",
       "Data variables:\n",
       "    air      (time, lat, lon) float32 dask.array<chunksize=(2920, 25, 25), meta=np.ndarray>\n",
       "Attributes:\n",
       "    Conventions:  COARDS\n",
       "    title:        4x daily NMC reanalysis (1948)\n",
       "    description:  Data is from NMC initialized reanalysis\\n(4x/day).  These a...\n",
       "    platform:     Model\n",
       "    references:   http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...
" ], "text/plain": [ "\n", "Dimensions: (lat: 25, time: 2920, lon: 53)\n", "Coordinates:\n", " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n", " * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n", "Data variables:\n", " air (time, lat, lon) float32 dask.array\n", "Attributes:\n", " Conventions: COARDS\n", " title: 4x daily NMC reanalysis (1948)\n", " description: Data is from NMC initialized reanalysis\\n(4x/day). These a...\n", " platform: Model\n", " references: http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly..." ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ds = xr.tutorial.open_dataset('air_temperature',\n", " chunks={'lat': 25, 'lon': 25, 'time': -1})\n", "ds" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quickly inspecting the `Dataset` above, we'll note that this `Dataset` has three _dimensions_ akin to axes in NumPy (`lat`, `lon`, and `time`), three _coordinate variables_ akin to `pandas.Index` objects (also named `lat`, `lon`, and `time`), and one data variable (`air`). Xarray also holds Dataset specific metadata as _attributes_." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:18.706930Z", "iopub.status.busy": "2022-07-27T19:14:18.706390Z", "iopub.status.idle": "2022-07-27T19:14:18.729049Z", "shell.execute_reply": "2022-07-27T19:14:18.728535Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'air' (time: 2920, lat: 25, lon: 53)>\n",
       "dask.array<open_dataset-ced301335a37488ca2d3a9447fa27157air, shape=(2920, 25, 53), dtype=float32, chunksize=(2920, 25, 25), chunktype=numpy.ndarray>\n",
       "Coordinates:\n",
       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n",
       "  * time     (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n",
       "Attributes:\n",
       "    long_name:     4xDaily Air temperature at sigma level 995\n",
       "    units:         degK\n",
       "    precision:     2\n",
       "    GRIB_id:       11\n",
       "    GRIB_name:     TMP\n",
       "    var_desc:      Air temperature\n",
       "    dataset:       NMC Reanalysis\n",
       "    level_desc:    Surface\n",
       "    statistic:     Individual Obs\n",
       "    parent_stat:   Other\n",
       "    actual_range:  [185.16 322.1 ]
" ], "text/plain": [ "\n", "dask.array\n", "Coordinates:\n", " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n", " * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n", "Attributes:\n", " long_name: 4xDaily Air temperature at sigma level 995\n", " units: degK\n", " precision: 2\n", " GRIB_id: 11\n", " GRIB_name: TMP\n", " var_desc: Air temperature\n", " dataset: NMC Reanalysis\n", " level_desc: Surface\n", " statistic: Individual Obs\n", " parent_stat: Other\n", " actual_range: [185.16 322.1 ]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "da = ds['air']\n", "da" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each data variable in xarray is called a `DataArray`. These are the fundamental labeled array objects in xarray. Much like the `Dataset`, `DataArrays` also have _dimensions_ and _coordinates_ that support many of its label-based opperations." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:18.732054Z", "iopub.status.busy": "2022-07-27T19:14:18.731747Z", "iopub.status.idle": "2022-07-27T19:14:18.742093Z", "shell.execute_reply": "2022-07-27T19:14:18.741568Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Array Chunk
Bytes 14.76 MiB 6.96 MiB
Shape (2920, 25, 53) (2920, 25, 25)
Count 4 Tasks 3 Chunks
Type float32 numpy.ndarray
\n", "
\n", " \n", "\n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", "\n", " \n", " \n", "\n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", "\n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", "\n", " \n", " 53\n", " 25\n", " 2920\n", "\n", "
" ], "text/plain": [ "dask.array" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "da.data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Accessing the underlying array of data is done via the `data` property. Here we can see that we have a Dask array. If this array were to be backed by a NumPy array, this property would point to the actual values in the array." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Use Standard Xarray Operations\n", "\n", "In almost all cases, operations using xarray objects are identical, regardless if the underlying data is stored as a Dask array or a NumPy array." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:18.744907Z", "iopub.status.busy": "2022-07-27T19:14:18.744498Z", "iopub.status.idle": "2022-07-27T19:14:18.810650Z", "shell.execute_reply": "2022-07-27T19:14:18.809976Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'air' (time: 2920, lat: 25, lon: 53, month: 12)>\n",
       "dask.array<sub, shape=(2920, 25, 53, 12), dtype=float32, chunksize=(2920, 25, 25, 1), chunktype=numpy.ndarray>\n",
       "Coordinates:\n",
       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n",
       "  * time     (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n",
       "  * month    (month) int64 1 2 3 4 5 6 7 8 9 10 11 12
" ], "text/plain": [ "\n", "dask.array\n", "Coordinates:\n", " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n", " * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n", " * month (month) int64 1 2 3 4 5 6 7 8 9 10 11 12" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "da2 = da.groupby('time.month').mean('time')\n", "da3 = da - da2\n", "da3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Call `.compute()` or `.load()` when you want your result as a `xarray.DataArray` with data stored as NumPy arrays.\n", "\n", "If you started `Client()` above then you may want to watch the status page during computation." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:18.813740Z", "iopub.status.busy": "2022-07-27T19:14:18.813301Z", "iopub.status.idle": "2022-07-27T19:14:20.374122Z", "shell.execute_reply": "2022-07-27T19:14:20.373492Z" } }, "outputs": [ { "data": { "text/plain": [ "numpy.ndarray" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "computed_da = da3.load()\n", "type(computed_da.data)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:20.377674Z", "iopub.status.busy": "2022-07-27T19:14:20.377307Z", "iopub.status.idle": "2022-07-27T19:14:20.429522Z", "shell.execute_reply": "2022-07-27T19:14:20.428835Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'air' (time: 2920, lat: 25, lon: 53, month: 12)>\n",
       "array([[[[-5.14987183e+00, -5.47715759e+00, -9.83168030e+00, ...,\n",
       "          -2.06136017e+01, -1.25448456e+01, -6.77099609e+00],\n",
       "         [-3.88607788e+00, -3.90576172e+00, -8.17987061e+00, ...,\n",
       "          -1.87125549e+01, -1.11448669e+01, -5.52117920e+00],\n",
       "         [-2.71517944e+00, -2.44839478e+00, -6.68945312e+00, ...,\n",
       "          -1.70036011e+01, -9.99716187e+00, -4.41302490e+00],\n",
       "         ...,\n",
       "         [-1.02611389e+01, -9.05839539e+00, -9.39399719e+00, ...,\n",
       "          -1.53933716e+01, -1.01606750e+01, -6.97190857e+00],\n",
       "         [-8.58795166e+00, -7.50210571e+00, -7.61483765e+00, ...,\n",
       "          -1.35699463e+01, -8.43449402e+00, -5.52383423e+00],\n",
       "         [-7.04670715e+00, -5.84384155e+00, -5.70956421e+00, ...,\n",
       "          -1.18162537e+01, -6.54209900e+00, -4.02824402e+00]],\n",
       "\n",
       "        [[-5.05761719e+00, -4.00010681e+00, -9.17195129e+00, ...,\n",
       "          -2.52222595e+01, -1.53296814e+01, -5.93362427e+00],\n",
       "         [-4.40733337e+00, -3.25991821e+00, -8.36616516e+00, ...,\n",
       "          -2.44294434e+01, -1.41292725e+01, -5.66036987e+00],\n",
       "         [-4.01040649e+00, -2.77757263e+00, -7.87347412e+00, ...,\n",
       "          -2.40147858e+01, -1.34914398e+01, -5.78581238e+00],\n",
       "...\n",
       "          -3.56890869e+00, -2.47412109e+00, -1.16558838e+00],\n",
       "         [ 6.08795166e-01,  1.47219849e+00,  1.11965942e+00, ...,\n",
       "          -3.59872437e+00, -2.50396729e+00, -1.15667725e+00],\n",
       "         [ 6.59942627e-01,  1.48742676e+00,  1.03787231e+00, ...,\n",
       "          -3.84628296e+00, -2.71829224e+00, -1.33132935e+00]],\n",
       "\n",
       "        [[ 5.35827637e-01,  4.01092529e-01,  3.08258057e-01, ...,\n",
       "          -1.68054199e+00, -1.12142944e+00, -1.90887451e-01],\n",
       "         [ 8.51684570e-01,  8.73504639e-01,  6.26892090e-01, ...,\n",
       "          -1.33462524e+00, -7.66601562e-01,  1.03210449e-01],\n",
       "         [ 1.04107666e+00,  1.23202515e+00,  8.63311768e-01, ...,\n",
       "          -1.06607056e+00, -5.31036377e-01,  3.14453125e-01],\n",
       "         ...,\n",
       "         [ 4.72015381e-01,  1.32940674e+00,  1.15509033e+00, ...,\n",
       "          -3.23403931e+00, -2.23956299e+00, -1.11035156e+00],\n",
       "         [ 4.14459229e-01,  1.23419189e+00,  1.07876587e+00, ...,\n",
       "          -3.47311401e+00, -2.56188965e+00, -1.37548828e+00],\n",
       "         [ 5.35278320e-02,  8.10333252e-01,  6.73461914e-01, ...,\n",
       "          -4.07232666e+00, -3.12890625e+00, -1.84762573e+00]]]],\n",
       "      dtype=float32)\n",
       "Coordinates:\n",
       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n",
       "  * time     (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n",
       "  * month    (month) int64 1 2 3 4 5 6 7 8 9 10 11 12
" ], "text/plain": [ "\n", "array([[[[-5.14987183e+00, -5.47715759e+00, -9.83168030e+00, ...,\n", " -2.06136017e+01, -1.25448456e+01, -6.77099609e+00],\n", " [-3.88607788e+00, -3.90576172e+00, -8.17987061e+00, ...,\n", " -1.87125549e+01, -1.11448669e+01, -5.52117920e+00],\n", " [-2.71517944e+00, -2.44839478e+00, -6.68945312e+00, ...,\n", " -1.70036011e+01, -9.99716187e+00, -4.41302490e+00],\n", " ...,\n", " [-1.02611389e+01, -9.05839539e+00, -9.39399719e+00, ...,\n", " -1.53933716e+01, -1.01606750e+01, -6.97190857e+00],\n", " [-8.58795166e+00, -7.50210571e+00, -7.61483765e+00, ...,\n", " -1.35699463e+01, -8.43449402e+00, -5.52383423e+00],\n", " [-7.04670715e+00, -5.84384155e+00, -5.70956421e+00, ...,\n", " -1.18162537e+01, -6.54209900e+00, -4.02824402e+00]],\n", "\n", " [[-5.05761719e+00, -4.00010681e+00, -9.17195129e+00, ...,\n", " -2.52222595e+01, -1.53296814e+01, -5.93362427e+00],\n", " [-4.40733337e+00, -3.25991821e+00, -8.36616516e+00, ...,\n", " -2.44294434e+01, -1.41292725e+01, -5.66036987e+00],\n", " [-4.01040649e+00, -2.77757263e+00, -7.87347412e+00, ...,\n", " -2.40147858e+01, -1.34914398e+01, -5.78581238e+00],\n", "...\n", " -3.56890869e+00, -2.47412109e+00, -1.16558838e+00],\n", " [ 6.08795166e-01, 1.47219849e+00, 1.11965942e+00, ...,\n", " -3.59872437e+00, -2.50396729e+00, -1.15667725e+00],\n", " [ 6.59942627e-01, 1.48742676e+00, 1.03787231e+00, ...,\n", " -3.84628296e+00, -2.71829224e+00, -1.33132935e+00]],\n", "\n", " [[ 5.35827637e-01, 4.01092529e-01, 3.08258057e-01, ...,\n", " -1.68054199e+00, -1.12142944e+00, -1.90887451e-01],\n", " [ 8.51684570e-01, 8.73504639e-01, 6.26892090e-01, ...,\n", " -1.33462524e+00, -7.66601562e-01, 1.03210449e-01],\n", " [ 1.04107666e+00, 1.23202515e+00, 8.63311768e-01, ...,\n", " -1.06607056e+00, -5.31036377e-01, 3.14453125e-01],\n", " ...,\n", " [ 4.72015381e-01, 1.32940674e+00, 1.15509033e+00, ...,\n", " -3.23403931e+00, -2.23956299e+00, -1.11035156e+00],\n", " [ 4.14459229e-01, 1.23419189e+00, 1.07876587e+00, ...,\n", " -3.47311401e+00, -2.56188965e+00, -1.37548828e+00],\n", " [ 5.35278320e-02, 8.10333252e-01, 6.73461914e-01, ...,\n", " -4.07232666e+00, -3.12890625e+00, -1.84762573e+00]]]],\n", " dtype=float32)\n", "Coordinates:\n", " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n", " * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n", " * month (month) int64 1 2 3 4 5 6 7 8 9 10 11 12" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "computed_da" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Persist data in memory\n", "\n", "If you have the available RAM for your dataset then you can persist data in memory. \n", "\n", "This allows future computations to be much faster." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:20.432764Z", "iopub.status.busy": "2022-07-27T19:14:20.432251Z", "iopub.status.idle": "2022-07-27T19:14:20.449806Z", "shell.execute_reply": "2022-07-27T19:14:20.444113Z" } }, "outputs": [], "source": [ "da = da.persist()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Time Series Operations\n", "\n", "Because we have a datetime index time-series operations work efficiently. Here we demo the use of xarray's resample method:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:20.452861Z", "iopub.status.busy": "2022-07-27T19:14:20.452409Z", "iopub.status.idle": "2022-07-27T19:14:20.707216Z", "shell.execute_reply": "2022-07-27T19:14:20.706694Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'air' (lat: 25, lon: 53)>\n",
       "dask.array<_sqrt, shape=(25, 53), dtype=float32, chunksize=(25, 25), chunktype=numpy.ndarray>\n",
       "Coordinates:\n",
       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0
" ], "text/plain": [ "\n", "dask.array<_sqrt, shape=(25, 53), dtype=float32, chunksize=(25, 25), chunktype=numpy.ndarray>\n", "Coordinates:\n", " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "da.resample(time='1w').mean('time').std('time')" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:20.718149Z", "iopub.status.busy": "2022-07-27T19:14:20.710650Z", "iopub.status.idle": "2022-07-27T19:14:22.778848Z", "shell.execute_reply": "2022-07-27T19:14:22.777972Z" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "da.resample(time='1w').mean('time').std('time').load().plot(figsize=(12, 8))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and rolling window operations:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:22.782427Z", "iopub.status.busy": "2022-07-27T19:14:22.781914Z", "iopub.status.idle": "2022-07-27T19:14:22.887586Z", "shell.execute_reply": "2022-07-27T19:14:22.885001Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'air' (time: 2920, lat: 25, lon: 53)>\n",
       "dask.array<truediv, shape=(2920, 25, 53), dtype=float64, chunksize=(2920, 25, 25), chunktype=numpy.ndarray>\n",
       "Coordinates:\n",
       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n",
       "  * time     (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n",
       "Attributes:\n",
       "    long_name:     4xDaily Air temperature at sigma level 995\n",
       "    units:         degK\n",
       "    precision:     2\n",
       "    GRIB_id:       11\n",
       "    GRIB_name:     TMP\n",
       "    var_desc:      Air temperature\n",
       "    dataset:       NMC Reanalysis\n",
       "    level_desc:    Surface\n",
       "    statistic:     Individual Obs\n",
       "    parent_stat:   Other\n",
       "    actual_range:  [185.16 322.1 ]
" ], "text/plain": [ "\n", "dask.array\n", "Coordinates:\n", " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n", " * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n", "Attributes:\n", " long_name: 4xDaily Air temperature at sigma level 995\n", " units: degK\n", " precision: 2\n", " GRIB_id: 11\n", " GRIB_name: TMP\n", " var_desc: Air temperature\n", " dataset: NMC Reanalysis\n", " level_desc: Surface\n", " statistic: Individual Obs\n", " parent_stat: Other\n", " actual_range: [185.16 322.1 ]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "da_smooth = da.rolling(time=30).mean().persist()\n", "da_smooth" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since xarray stores each of its coordinate variables in memory, slicing by label is trivial and entirely lazy." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:22.897318Z", "iopub.status.busy": "2022-07-27T19:14:22.895132Z", "iopub.status.idle": "2022-07-27T19:14:22.941105Z", "shell.execute_reply": "2022-07-27T19:14:22.940345Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 1.05 ms, sys: 2.82 ms, total: 3.87 ms\n", "Wall time: 7.08 ms\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'air' (lat: 25, lon: 53)>\n",
       "dask.array<getitem, shape=(25, 53), dtype=float32, chunksize=(25, 25), chunktype=numpy.ndarray>\n",
       "Coordinates:\n",
       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n",
       "    time     datetime64[ns] 2013-01-01T18:00:00\n",
       "Attributes:\n",
       "    long_name:     4xDaily Air temperature at sigma level 995\n",
       "    units:         degK\n",
       "    precision:     2\n",
       "    GRIB_id:       11\n",
       "    GRIB_name:     TMP\n",
       "    var_desc:      Air temperature\n",
       "    dataset:       NMC Reanalysis\n",
       "    level_desc:    Surface\n",
       "    statistic:     Individual Obs\n",
       "    parent_stat:   Other\n",
       "    actual_range:  [185.16 322.1 ]
" ], "text/plain": [ "\n", "dask.array\n", "Coordinates:\n", " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n", " time datetime64[ns] 2013-01-01T18:00:00\n", "Attributes:\n", " long_name: 4xDaily Air temperature at sigma level 995\n", " units: degK\n", " precision: 2\n", " GRIB_id: 11\n", " GRIB_name: TMP\n", " var_desc: Air temperature\n", " dataset: NMC Reanalysis\n", " level_desc: Surface\n", " statistic: Individual Obs\n", " parent_stat: Other\n", " actual_range: [185.16 322.1 ]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%time da.sel(time='2013-01-01T18:00:00')" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:22.947428Z", "iopub.status.busy": "2022-07-27T19:14:22.946356Z", "iopub.status.idle": "2022-07-27T19:14:23.075228Z", "shell.execute_reply": "2022-07-27T19:14:23.074353Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 23.5 ms, sys: 7.2 ms, total: 30.7 ms\n", "Wall time: 91.1 ms\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'air' (lat: 25, lon: 53)>\n",
       "array([[241.89   , 241.79999, 241.79999, ..., 234.39   , 235.5    ,\n",
       "        237.59999],\n",
       "       [246.29999, 245.29999, 244.2    , ..., 230.89   , 231.5    ,\n",
       "        234.5    ],\n",
       "       [256.6    , 254.7    , 252.09999, ..., 230.7    , 231.79999,\n",
       "        236.09999],\n",
       "       ...,\n",
       "       [296.6    , 296.4    , 296.     , ..., 296.5    , 295.79   ,\n",
       "        295.29   ],\n",
       "       [297.     , 297.5    , 297.1    , ..., 296.79   , 296.6    ,\n",
       "        296.29   ],\n",
       "       [297.5    , 297.69998, 297.5    , ..., 297.79   , 298.     ,\n",
       "        297.9    ]], dtype=float32)\n",
       "Coordinates:\n",
       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n",
       "    time     datetime64[ns] 2013-01-01T18:00:00\n",
       "Attributes:\n",
       "    long_name:     4xDaily Air temperature at sigma level 995\n",
       "    units:         degK\n",
       "    precision:     2\n",
       "    GRIB_id:       11\n",
       "    GRIB_name:     TMP\n",
       "    var_desc:      Air temperature\n",
       "    dataset:       NMC Reanalysis\n",
       "    level_desc:    Surface\n",
       "    statistic:     Individual Obs\n",
       "    parent_stat:   Other\n",
       "    actual_range:  [185.16 322.1 ]
" ], "text/plain": [ "\n", "array([[241.89 , 241.79999, 241.79999, ..., 234.39 , 235.5 ,\n", " 237.59999],\n", " [246.29999, 245.29999, 244.2 , ..., 230.89 , 231.5 ,\n", " 234.5 ],\n", " [256.6 , 254.7 , 252.09999, ..., 230.7 , 231.79999,\n", " 236.09999],\n", " ...,\n", " [296.6 , 296.4 , 296. , ..., 296.5 , 295.79 ,\n", " 295.29 ],\n", " [297. , 297.5 , 297.1 , ..., 296.79 , 296.6 ,\n", " 296.29 ],\n", " [297.5 , 297.69998, 297.5 , ..., 297.79 , 298. ,\n", " 297.9 ]], dtype=float32)\n", "Coordinates:\n", " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n", " time datetime64[ns] 2013-01-01T18:00:00\n", "Attributes:\n", " long_name: 4xDaily Air temperature at sigma level 995\n", " units: degK\n", " precision: 2\n", " GRIB_id: 11\n", " GRIB_name: TMP\n", " var_desc: Air temperature\n", " dataset: NMC Reanalysis\n", " level_desc: Surface\n", " statistic: Individual Obs\n", " parent_stat: Other\n", " actual_range: [185.16 322.1 ]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%time da.sel(time='2013-01-01T18:00:00').load()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Custom workflows and automatic parallelization" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Almost all of xarray’s built-in operations work on Dask arrays. If you want to use a function that isn’t wrapped by xarray, one option is to extract Dask arrays from xarray objects (.data) and use Dask directly.\n", "\n", "Another option is to use xarray’s `apply_ufunc()` function, which can automate embarrassingly parallel “map” type operations where a function written for processing NumPy arrays should be repeatedly applied to xarray objects containing Dask arrays. It works similarly to `dask.array.map_blocks()` and `dask.array.blockwise()`, but without requiring an intermediate layer of abstraction.\n", "\n", "Here we show an example using NumPy operations and a fast function from `bottleneck`, which we use to calculate Spearman’s rank-correlation coefficient:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:23.081037Z", "iopub.status.busy": "2022-07-27T19:14:23.078773Z", "iopub.status.idle": "2022-07-27T19:14:23.095483Z", "shell.execute_reply": "2022-07-27T19:14:23.093372Z" } }, "outputs": [], "source": [ "import numpy as np\n", "import xarray as xr\n", "import bottleneck\n", "\n", "def covariance_gufunc(x, y):\n", " return ((x - x.mean(axis=-1, keepdims=True))\n", " * (y - y.mean(axis=-1, keepdims=True))).mean(axis=-1)\n", "\n", "def pearson_correlation_gufunc(x, y):\n", " return covariance_gufunc(x, y) / (x.std(axis=-1) * y.std(axis=-1))\n", "\n", "def spearman_correlation_gufunc(x, y):\n", " x_ranks = bottleneck.rankdata(x, axis=-1)\n", " y_ranks = bottleneck.rankdata(y, axis=-1)\n", " return pearson_correlation_gufunc(x_ranks, y_ranks)\n", "\n", "def spearman_correlation(x, y, dim):\n", " return xr.apply_ufunc(\n", " spearman_correlation_gufunc, x, y,\n", " input_core_dims=[[dim], [dim]],\n", " dask='parallelized',\n", " output_dtypes=[float])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the examples above, we were working with an some air temperature data. For this example, we'll calculate the spearman correlation using the raw air temperature data with the smoothed version that we also created (`da_smooth`). For this, we'll also have to rechunk the data ahead of time." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:23.103207Z", "iopub.status.busy": "2022-07-27T19:14:23.101006Z", "iopub.status.idle": "2022-07-27T19:14:23.163083Z", "shell.execute_reply": "2022-07-27T19:14:23.162556Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 'air' (lat: 25, lon: 53)>\n",
       "dask.array<transpose, shape=(25, 53), dtype=float64, chunksize=(25, 25), chunktype=numpy.ndarray>\n",
       "Coordinates:\n",
       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0
" ], "text/plain": [ "\n", "dask.array\n", "Coordinates:\n", " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "corr = spearman_correlation(da.chunk({'time': -1}),\n", " da_smooth.chunk({'time': -1}),\n", " 'time')\n", "corr" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "execution": { "iopub.execute_input": "2022-07-27T19:14:23.167769Z", "iopub.status.busy": "2022-07-27T19:14:23.166590Z", "iopub.status.idle": "2022-07-27T19:14:23.849126Z", "shell.execute_reply": "2022-07-27T19:14:23.848425Z" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "corr.plot(figsize=(12, 8))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.12" } }, "nbformat": 4, "nbformat_minor": 4 }