Xarray: sémantické rozšíření n-rozměrných polí z knihovny NumPy

31. 10. 2023
Doba čtení: 38 minut

Sdílet

 Autor: PCWorld.com
Seznámíme se s knihovnou nazvanou Xarray, která rozšiřuje běžná n-rozměrná pole (ND-array) z knihovny NumPy, protože k polím přidává další sémantické informace: jména os, souřadnice (koordináty) na jednotlivých osách a další.

Obsah

1. Xarray: sémantické rozšíření n-rozměrných polí z knihovny NumPy

2. Instalace balíčku xarray i jeho tranzitivních závislostí

3. Instalace při použití správce balíčků PDM

4. Kontrola instalace

5. Datový typ DataArray

6. Pojmenování os (dimenzí), specifikace souřadnic v jednotlivých dimenzích, pojmenování pole

7. Přiřazení dalších uživatelských atributů

8. Vícedimenzionální koordináty, 3D pole

9. Přístup k atributům polí

10. Uložení polí do formátu NetCDF

11. Přečtení koordinát na zvolené ose ve formě nového pole

12. Použití číselných indexů při přístupu k prvkům n-dimenzionálních polí

13. Využití operací isel a sel při přístupu k prvkům n-dimenzionálních polí

14. Základní aritmetické a relační operace s polem (broadcasting)

15. Konverze pole operací where

16. Množina polí: datový typ DataSet

17. Dataset s dvojicí trojrozměrných polí

18. Operace nad poli s odlišnou souřadnou mřížkou

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Xarray: sémantické rozšíření n-rozměrných polí z knihovny NumPy

V dnešním článku o programovacím jazyku Python se seznámíme s potenciálně velmi užitečnou knihovnou nazvanou Xarray. Tato knihovna rozšiřuje běžná n-rozměrná pole (ND-array) z knihovny NumPy, protože k těmto polím přidává další sémantické informace. Zejména jsou pole rozšířena o jména souřadných os (tzv. dimenze), o souřadnice (koordináty) na jednotlivých osách, ale taktéž o metainformace přidané uživatelem atd. Tyto informace mohou být uloženy společně s prvky polí do souborů ve standardním (a standardizovaném) formátu NetCDF, což umožňuje jak import dat s metainformacemi, tak i jejich sdílení mezi různými systémy. Navíc je možné s dimenzemi a koordináty dále pracovat, což si ukážeme na několika demonstračních příkladech (nejedná se tedy o pouhá statická data).

Poznámka: původně se knihovna Xarray jmenovala jen xray.

Obrázek 1: Logo knihovny xarray.

Jen pro zajímavost se podívejme, jak by bylo možné reprezentovat pozici figurek na šachovnici s tím, že obě osy jsou pojmenovány (files a ranks jsou oficiální jména používaná namísto sloupců a řádků) a navíc jsou použity „sémantické“ souřadnice, tedy označení sloupců písmeny a řádků čísly 1–8 (namísto použití celočíselných indexů 0 až 7). K poli reprezentujícím šachovnici jsou navíc přidány i další metainformace: jméno a uživatské atributy:

import numpy as np
import xarray as xr
 
chessboard = np.array([" "]*64).reshape(8, 8)
chessboard[0, 0] = "♚"
chessboard[1, 5] = "♔"
chessboard[2, 5] = "♙"
chessboard[3, 4] = "♜"
 
files = ["a", "b", "c", "d", "e", "f", "g", "h"]
ranks = np.linspace(1, 8, 8, dtype=np.int8)
 
array = xr.DataArray(chessboard,
                     name="Saavedra position",
                     dims=("files", "ranks"),
                     coords={"files":files, "ranks":ranks})
 
array.attrs["units"] = "chess pieces"
array.attrs["description"] ="White to move and win",
array.attrs["metadata"] = {"played by": "Fernando Saavedra",
                           "winner": "white",
                           "see also": "https://www.youtube.com/watch?v=Mg2OOsQPURs",}
 
print(array)
print()
 
# výběr sloupce
print(array.sel(files="c"))
print()
 
# výběr řádku
print(array.sel(ranks=6))
print()

2. Instalace balíčku xarray i jeho tranzitivních závislostí

Balíček xarray je dostupný na PyPi, takže je jeho instalace snadná. V případě, že již máte nainstalovány základní závislosti, což jsou v tomto konkrétním případě knihovny Numpy a Pandas, proběhne instalace prakticky okamžitě:

$ pip3 install --user xarray
 
Collecting xarray
  Downloading xarray-0.16.2-py3-none-any.whl (736 kB)
     |████████████████████████████████| 736 kB 1.0 MB/s
Collecting setuptools>=38.4
  Downloading setuptools-59.6.0-py3-none-any.whl (952 kB)
     |████████████████████████████████| 952 kB 2.1 MB/s
Requirement already satisfied: pandas>=0.25 in ./.local/lib/python3.6/site-packages (from xarray) (1.1.4)
Requirement already satisfied: numpy>=1.15 in ./.local/lib/python3.6/site-packages (from xarray) (1.19.4)
Requirement already satisfied: python-dateutil>=2.7.3 in ./.local/lib/python3.6/site-packages (from pandas>=0.25->xarray) (2.8.1)
Requirement already satisfied: pytz>=2017.2 in /usr/lib/python3.6/site-packages (from pandas>=0.25->xarray) (2017.2)
Requirement already satisfied: six>=1.5 in ./.local/lib/python3.6/site-packages (from python-dateutil>=2.7.3->pandas>=0.25->xarray) (1.11.0)
Installing collected packages: setuptools, xarray
Successfully installed setuptools-59.6.0 xarray-0.16.2

Na počítači s „čistou“ instalací Pythonu a nástroje pip se navíc musí nainstalovat i všechny potřebné závislosti, což jsou především již výše zmíněné knihovny Numpy a Pandas. Instalace tedy potrvá déle, protože je nutné stáhnout několik megabajtů s tranzitivně závislými (to je tedy slovní spojení!) balíčky:

$ pip3 install --user xarray
Collecting xarray
  Downloading xarray-2023.1.0-py3-none-any.whl (973 kB)
     |████████████████████████████████| 973 kB 1.5 MB/s
Collecting numpy>=1.20
  Downloading numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (17.3 MB)
     |████████████████████████████████| 17.3 MB 3.1 MB/s
Collecting packaging>=21.3
  Downloading packaging-23.2-py3-none-any.whl (53 kB)
     |████████████████████████████████| 53 kB 963 kB/s
Collecting pandas>=1.3
  Downloading pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.4 MB)
     |████████████████████████████████| 12.4 MB 4.3 MB/s
Collecting python-dateutil>=2.8.2
  Downloading python_dateutil-2.8.2-py2.py3-none-any.whl (247 kB)
     |████████████████████████████████| 247 kB 3.1 MB/s
Collecting tzdata>=2022.1
  Downloading tzdata-2023.3-py2.py3-none-any.whl (341 kB)
     |████████████████████████████████| 341 kB 3.1 MB/s
Collecting pytz>=2020.1
  Downloading pytz-2023.3.post1-py2.py3-none-any.whl (502 kB)
     |████████████████████████████████| 502 kB 3.2 MB/s
Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.8.2->pandas>=1.3->xarray) (1.14.0)
Installing collected packages: numpy, packaging, python-dateutil, tzdata, pytz, pandas, xarray
Successfully installed numpy-1.24.4 packaging-23.2 pandas-2.0.3 python-dateutil-2.8.2 pytz-2023.3.post1 tzdata-2023.3 xarray-2023.1.0

3. Instalace při použití správce balíčků PDM

Knihovnu xarray je pochopitelně možné nastavit i jako závislý balíček (přímá závislost, popř. vývojová závislost) při použití nástroje PDM, který byl na Rootu popsán předminulý týden. Ukažme si pro úplnost, jak by mohl vypadat projekt, který je na knihovně xarray postaven.

Nejprve si necháme vytvořit kostru nového projektu (prozatím bez závislostí):

$ pdm init

Poctivě odpovíme na položené otázky (většinou jen potvrzením klávesou Enter, další odpovědi jsou označeny tučně):

Creating a pyproject.toml for PDM...
Please enter the Python interpreter to use
0. /usr/bin/python (3.11)
1. /usr/bin/python3.11 (3.11)
2. /usr/bin/python3 (3.11)
Please select (0): 0
Would you like to create a virtualenv with /usr/bin/python? [y/n] (y): y
Virtualenv is created successfully at /home/ptisnovs/test2/.venv
Is the project a library that is installable?
If yes, we will need to ask a few more questions to include the project name and build backend [y/n] (n): n
License(SPDX name) (MIT):
Author name (): Pavel Tisnovsky
Author email (): tisnik@nowhere.us
Python requires('*' to allow any) (>=3.8):
Project is initialized successfully

Do právě vzniklého projektu ve druhém kroku přidáme závislost na balíčku xarray:

$ pdm add xarray

V tomto kroku by se měly nainstalovat stejné balíčky, jako při instalaci přes pip (viz předchozí kapitolu):

Adding packages to default dependencies: xarray
🔒 Lock successful
Changes are written to pyproject.toml.
Synchronizing working set with resolved packages: 7 to add, 0 to update, 0 to
remove
 
  ✔ Install six 1.16.0 successful
  ✔ Install packaging 23.2 successful
  ✔ Install python-dateutil 2.8.2 successful
  ✔ Install xarray 2023.1.0 successful
  ✔ Install tzdata 2023.3 successful
  ✔ Install pytz 2023.3.post1 successful
  ✔ Install pandas 2.0.3 successful
 
🎉 All complete!

A výsledný projektový soubor by měl vypadat následovně:

[project]
name = ""
version = ""
description = ""
authors = [
    {name = "", email = ""},
]
dependencies = [
    "numpy>=1.24.4",
    "xarray>=2023.1.0",
]
requires-python = ">=3.8"
readme = "README.md"
license = {text = "MIT"}

4. Kontrola instalace

Kontrola, zda instalace proběhla v pořádku, bude prozatím velmi jednoduchá. Naimportujeme knihovnu xarray a necháme si k ní zobrazit nápovědu, což je triviální:

import xarray as xr
 
help(xr)

Po spuštění tohoto skriptu, popř. při zadání obou příkazů do interaktivního prostředí Pythonu by se měla zobrazit nápověda k balíčku (a pochopitelně i import by měl proběhnout bez vyhození výjimky):

Help on package xarray:
 
NAME
    xarray
 
PACKAGE CONTENTS
    backends (package)
    coding (package)
    conventions
    convert
    core (package)
    indexes (package)
    plot (package)
    static (package)
    testing
    tests (package)
    tutorial
    util (package)
 
CLASSES
    ...
    ...
    ...

5. Datový typ DataArray

Základním datovým typem, nad nímž je knihovna xarray postavena, je typ nazvaný DataArray. Jedná se o obecné n-rozměrné homogenní pole, které ovšem může mít pojmenované jednotlivé osy (dimenze), může mít specifikovány souřadnice v n-rozměrné mřížce (například se může jednat o časová razítka atd.) a dokonce můžeme poli přiřadit i další atributy. Důležité je, že tyto atributy jsou zachovány i při provádění různých operací s tímto datovým typem:

Help on class DataArray in module xarray.core.dataarray:
 
class DataArray(xarray.core.common.AbstractArray, xarray.core.common.DataWithCoords, xarray.core.arithmetic.DataArrayArithmetic, xarray.core._aggregations.DataArrayAggregations)
 |  DataArray(data: 'Any' = <NA>, coords: 'Sequence[Sequence[Any] | pd.Index | DataArray] | Mapping[Any, Any] | None' = None, dims: 'Hashable | Sequence[Hashable] | None' = None, name: 'Hashable | None' = None, attrs: 'Mapping | None' = None, indexes: 'dict[Hashable, Index] | None' = None, fastpath: 'bool' = False) -> 'None'
 |
 |  N-dimensional array with labeled coordinates and dimensions.
 |
 |  DataArray provides a wrapper around numpy ndarrays that uses
 |  labeled dimensions and coordinates to support metadata aware
 |  operations. The API is similar to that for the pandas Series or
 |  DataFrame, but DataArray objects can have any number of dimensions,
 |  and their contents have fixed data types.
 |
 |  Additional features over raw numpy arrays:
 |
 |  - Apply operations over dimensions by name: ``x.sum('time')``.
 |  - Select or assign values by integer location (like numpy):
 |    ``x[:10]`` or by label (like pandas): ``x.loc['2014-01-01']`` or
 |    ``x.sel(time='2014-01-01')``.
 |  - Mathematical operations (e.g., ``x - y``) vectorize across
 |    multiple dimensions (known in numpy as "broadcasting") based on
 |    dimension names, regardless of their original order.
 |  - Keep track of arbitrary metadata in the form of a Python
 |    dictionary: ``x.attrs``
 |  - Convert to a pandas Series: ``x.to_series()``.
 |
 |  Getting items from or doing mathematical operations with a
 |  DataArray always returns another DataArray.
 ...
 ...
 ...
Poznámka: interně se zde využívají n-rozměrná pole z balíčku Numpy.

Podívejme se nyní, jak lze takové pole vytvořit. Do konstruktoru DataArray můžeme v tom nejjednodušším případě předat n-rozměrné pole z Numpy, například jednotkovou matici vytvořenou konstruktorem numpy.identity(řád matice):

import numpy as np
import xarray as xr
 
array = xr.DataArray(np.identity(10))
print(array)

Funkce print zobrazí obsah objektu DataArray v čitelné podobě:

<xarray.DataArray (dim_0: 10, dim_1: 10)>
array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
Dimensions without coordinates: dim_0, dim_1
Poznámka: povšimněte si poznámky o osách (dimenzích) bez explicitně specifikovaných souřadnic. K tomuto problému se vrátíme v dalším textu.

6. Pojmenování os (dimenzí), specifikace souřadnic v jednotlivých dimenzích, pojmenování pole

Osy (zde nazývané dimenze) mají výchozí jméno „dim0“, „dim1“ atd. (podle počtu dimenzí pole). Tyto nicneříkající názvy můžeme přejmenovat při vytváření objektu typu DataArray specifikací nepovinného parametru dims. Je to snadné – konstruktoru postačí předat n-tici či seznam s názvy:

import numpy as np
import xarray as xr
 
array = xr.DataArray(np.identity(10),
                     dims=("x", "y"))
print(array)

Názvy os (dimenzí) se po spuštění tohoto skriptu zobrazí ve výsledku:

<xarray.DataArray (x: 10, y: 10)>
array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
Dimensions without coordinates: x, y

Stejně důležité je v praxi specifikace souřadnic v jednotlivých souřadných osách. Prvky pole tedy budou mít kromě celočíselných indexů přiřazeny i konkrétní souřadnice (například polohu, teplotu, čas, atd.). Podívejme se, jak lze specifikovat souřadnice v ose, kterou jsme si explicitně pojmenovali „x“. Souřadnice se předávají ve slovníku coords:

import numpy as np
import xarray as xr
 
array = xr.DataArray(np.identity(10),
                     dims=("x", "y"),
                     coords={"x":[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]})
print(array)

Výsledné pole (povšimněte si sekce Coordinates i sekce navazující):

<xarray.DataArray (x: 10, y: 10)>
array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
Coordinates:
  * x        (x) int64 10 20 30 40 50 60 70 80 90 100
Dimensions without coordinates: y

Samozřejmě nám nic nebrání ve specifikaci souřadnic pro obě osy našeho dvourozměrného pole. Tentokrát budou souřadnice specifikovány vektorem:

import numpy as np
import xarray as xr
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
array = xr.DataArray(np.identity(10),
                     dims=("x", "y"),
                     coords={"x":xcoords, "y":ycoords})
print(array)

Výsledek:

<xarray.DataArray (x: 10, y: 10)>
array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
Coordinates:
  * x        (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0

A konečně ještě poli přiřadíme nějaké jméno, což je další standardní atribut:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(10, 10)
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y"),
                     coords={"x":xcoords, "y":ycoords})

print(array)

Nyní může výsledek vypadat následovně:

<xarray.DataArray 'Temperature measurement' (x: 10, y: 10)>
array([[ 2.32647600e+01,  2.80514346e+00,  1.55639979e+01,
        -8.66640844e+00,  1.02604000e+01,  1.43061846e+01,
        -1.50550198e+00,  1.15990642e+01,  2.33254049e+01,
         2.33481511e+01],
       [ 1.67234930e+01,  2.51284240e+01,  5.54117143e+00,
        -5.58609990e+00,  2.67385215e+01, -9.45194606e+00,
         2.69381374e+01, -2.64076192e+00,  1.76559359e+00,
         2.17843960e+01],
         ...
         ...
         ...
       [ 1.18639075e+01,  2.75731272e+01,  2.09509091e+01,
         1.56939796e+01,  2.43195638e+01,  1.36336352e+01,
         1.56647959e+01,  2.36473805e+01,  2.77993553e+01,
         1.35592233e+01],
       [-1.64663391e+00, -1.18151743e+00,  1.86746830e+01,
        -1.54580596e+00,  6.31361942e+00, -8.33521270e+00,
         9.62469380e+00,  1.19293630e+00, -8.01198193e+00,
         3.77753591e+00]])
Coordinates:
  * x        (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0

7. Přiřazení dalších uživatelských atributů

K polím, resp. přesněji řečeno k objektům typu DataArray, lze snadno přiřadit i další atributy, které mohou být libovolného typu (jen je nutné si dát pozor na případné problémy při ukládání polí do formátu netCDF, což si ukážeme dále). V dalším demonstračním příkladu do vytvořeného pole přidáme několik dalších pojmenovaných atributů zápisem do slovníku DataArray.attrs. Povšimněte si, že hodnotami mohou být například i další slovníky, n-tice atd. atd.:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(10, 10)
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y"),
                     coords={"x":xcoords, "y":ycoords})
 
array.attrs["units"] = "centigrees"
array.attrs["description"] ="Local temperature values measured in grid",
array.attrs["measured by"] = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
 
print(array)

Atributy jsou vypsány společně se všemi dalšími informacemi o poli:

<xarray.DataArray 'Temperature measurement' (x: 10, y: 10)>
array([[10.5832851 , -2.32490932, -5.5881393 ,  0.418035  , 10.60766768,
        24.48854489, 14.06688637, -8.7774459 ,  5.05229998, -1.11231137],
       [17.7745931 , -6.78789311,  1.63416214, 10.47049785, -8.0736508 ,
         7.89837523, 19.39429883, -6.35163393, 18.23288826, -8.52934274],
       [17.01104059, -2.77683528,  6.76134728,  5.36721515,  9.62797089,
        11.25519146, 17.77977519, -2.85977703, -9.77967287,  5.53854267],
       [16.39795885, 15.3228364 , 24.77271425, 23.84860142, 12.59105118,
        26.71223278, 12.93472326, 12.87686291,  2.38745519, -9.89202765],
       [ 0.43474102,  3.90017104, 11.66830096, 17.85339982, -8.94414913,
        -0.95883465, -7.04423858, -0.99590894, -5.34842274,  0.05459278],
       [22.93909906,  6.71161717, 19.96209108, -8.56968358, -6.4280693 ,
        -4.74889956,  7.48179102, 14.95668487, 26.34024394, 20.73641704],
       [20.35649459,  4.91876629, -1.81175122, -7.98758547, -8.3296374 ,
        13.6681342 , -1.54770907, 19.54327137,  2.00960747, 19.51355718],
       [ 7.26390215,  5.07340915, -8.7700297 ,  2.30132815, 28.69651615,
         4.44835462,  1.50046012, 26.87604918, 18.78270925, -5.10117866],
       [14.30112364,  0.50389193,  6.99194032, -8.30147546, 21.33919   ,
        -6.77261547, -0.92636757,  4.08006382, 15.24589196, 12.08606029],
       [ 4.580669  , 10.00008772, 15.56234634, -6.53134212, 11.8121812 ,
        -6.37603482, 10.71300997, 25.90596186, 17.79681462,  9.47069227]])
Coordinates:
  * x        (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0
Attributes:
    units:        centigrees
    description:  ('Local temperature values measured in grid',)
    measured by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...

Alternativně je možné atributy nastavit přímo při konstrukci pole typu DataArray, a to specifikací nepovinného atributu attrs. Tento postup je ukázán na dalším příkladu:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(10, 10)
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y"),
                     coords={"x":xcoords, "y":ycoords},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
Poznámka: v tomto a dalších příkladech explicitně používám konstruktor dict pro uživatelské atributy. Samozřejmě je však možné použít přímo „literál“ ve formě {prvky_slovníku}. Výsledek bude totožný.

Výsledek bude vypadat takto:

<xarray.DataArray 'Temperature measurement' (x: 10, y: 10)>
array([[23.2576271 , -2.15779202, 17.5443984 , 21.07597796, 10.56049287,
        29.07426336, -3.65466472,  9.79700303, 11.76340949, 14.79519823],
       [24.63298382, 17.74715879,  0.60019018, -0.8598743 ,  5.07014205,
        11.37652831,  2.25657343, 21.52399783, -2.36153402, 11.16127697],
       [17.38473719,  4.88292401, 16.746297  ,  2.73729571, 20.98158579,
        19.05244522, -7.10327481, 19.02122539,  5.72791239, 23.42325136],
       [29.63847975, 22.97463667, -8.71680645, 23.17846176, -1.50461374,
        -2.5930478 , 14.94336694, 26.55283565,  1.77010509, 26.68586834],
       [ 6.26370305, 15.29240368, 24.82652106, 28.41207708, 25.02094536,
         1.58548248, -9.07739674, 24.42454772, 27.31781816, 18.87826056],
       [ 8.61993635, 19.14889656, 19.76866295, 17.83522801, -3.56479117,
        18.59088179, 29.7079522 , -7.79032716, 22.02287043, 28.06321914],
       [-5.07439459, -2.55489334, -6.80073133, -8.11352206, 14.07990422,
         4.10234674, 14.97487831, 21.35397355,  2.77982491,  6.14347479],
       [ 0.44349296, 29.28705309,  3.74470177,  3.58964699,  9.63450628,
        -3.01921671,  6.1531892 , 16.83808275, -1.46114794, 22.98582524],
       [-0.25700688, 16.88119187, -8.86471902, 21.76825227, -8.78371084,
        20.8501691 , 27.77968551, -7.85864626, -9.07993012, -8.70373661],
       [-4.28096512, 22.95255284,  8.17621111, 19.76970543, 11.0936614 ,
        -4.10484249, 26.17673632, -0.80783274, -1.92738157, -4.07289025]])
Coordinates:
  * x        (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...

8. Vícedimenzionální koordináty, 3D pole

Knihovna xarray umožňuje používat i takzvané vícedimenzionální koordináty. Je to ukázáno na dalším příkladu, v němž se používají logické koordináty longitues a latitudes, které jsou odvozeny z fyzických koordinát reprezentovaných hodnotami na osách x a y. Takto zapsané koordináty se používají například při vykreslování, což je téma navazujícího článku:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(2, 2)
 
longitudes = [[-99.83, -99.32], [-99.79, -99.23]]
latitudes = [[42.25, 42.21], [42.63, 42.59]]
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y"),
                     coords=dict(
                        lon=(["x", "y"], longitudes),
                        lat=(["x", "y"], latitudes),
                     ),
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)

Z výpisu je patrné, že pole má stále velikost pouze 2×2 prvky:

array([[19.06037142, -7.87284455],
       [27.94244297, 10.81820761]])
Coordinates:
    lon      (x, y) float64 -99.83 -99.32 -99.79 -99.23
    lat      (x, y) float64 42.25 42.21 42.63 42.59
Dimensions without coordinates: x, y
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
Poznámka: v tomto konkrétním případě budeme moci při přístupu k prvkům používat metodu „nearest“, která nalezne i prvek v případě, že zadáme koordináty, které leží mimo přesné hodnoty na osách. Opět se jedná o téma, kterému se budeme podrobněji věnovat příště.

Nezávisle na volbě koordinát samozřejmě můžeme pracovat i s vícerozměrnými poli. Příkladem může být pole se třemi osami (dimenzemi), kde třetí dimenzí bude čas:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(2, 2, 3)
 
longitudes = [[-99.83, -99.32], [-99.79, -99.23]]
latitudes = [[42.25, 42.21], [42.63, 42.59]]
times = ["2023-10-01", "2023-10-02", "2023-10-03"]
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y", "time"),
                     coords=dict(
                        lon=(["x", "y"], longitudes),
                        lat=(["x", "y"], latitudes),
                        time=times,
                     ),
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
Poznámka: ve skutečnosti se nejedná o příliš dobrý příklad, protože časové hodnoty by měly být reprezentovány typem numpy.timedelta, protože jen tehdy budou dostupné i mnohé složitější selektory.

Výsldek:

array([[[ 1.09668425,  2.00419139,  5.51502503],
        [20.53512088, -4.33673027, 18.02246637]],

       [[25.73788498, -2.226619  , 19.64667429],
        [ 0.55226708,  3.82939432, 11.70746199]]])
Coordinates:
    lon      (x, y) float64 -99.83 -99.32 -99.79 -99.23
    lat      (x, y) float64 42.25 42.21 42.63 42.59
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Dimensions without coordinates: x, y
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
Poznámka: v bloku Coordinates jsou hvězdičkou označeny jednodimenzionální koordináty.

9. Přístup k atributům polí

Velmi snadno je možné přistupovat k následujícím atributům objektu DataArray: jeho jménu, uloženým hodnotám, koordinátům, dimenzím a taktéž k uživatelským atributům. Je to velmi snadné – použije se standardní tečková notace tak, jak je to ukázáno v následujícím demonstračním příkladu:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(2, 2, 3)
 
longitudes = [[-99.83, -99.32], [-99.79, -99.23]]
latitudes = [[42.25, 42.21], [42.63, 42.59]]
times = ["2023-10-01", "2023-10-02", "2023-10-03"]
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y", "time"),
                     coords=dict(
                        lon=(["x", "y"], longitudes),
                        lat=(["x", "y"], latitudes),
                        time=times,
                     ),
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
print()
print()
 
print("Name")
print(array.name)
print()
 
print("Values")
print(array.values)
print()
 
print("Coords")
print(array.coords)
print()
 
print("Attributes")
print(array.attrs)
print()

Zobrazené výsledky ukazují, jaké informace jsou v jednotlivých atributech uloženy (nadpisy jsem zvýraznil ručně):

<xarray.DataArray 'Temperature measurement' (x: 2, y: 2, time: 3)>
array([[[-2.25069401, -1.24318547, -8.79751399],
        [ 8.69104338, 29.770204  , -0.62751908]],

       [[ 7.60403569, 16.76061332, 10.71663607],
        [ 2.55393168, 20.98851206,  4.2413965 ]]])
Coordinates:
    lon      (x, y) float64 -99.83 -99.32 -99.79 -99.23
    lat      (x, y) float64 42.25 42.21 42.63 42.59
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Dimensions without coordinates: x, y
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
 
 
Name
Temperature measurement
 
Values
[[[-2.25069401 -1.24318547 -8.79751399]
  [ 8.69104338 29.770204   -0.62751908]]
 
 [[ 7.60403569 16.76061332 10.71663607]
  [ 2.55393168 20.98851206  4.2413965 ]]]
 
Coords
Coordinates:
    lon      (x, y) float64 -99.83 -99.32 -99.79 -99.23
    lat      (x, y) float64 42.25 42.21 42.63 42.59
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
 
Attributes
{'units': 'centigrees', 'description': 'Local temperature values measured in grid', 'measured_by': {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, 0, 0)}}

10. Uložení polí do formátu NetCDF

Knihovna xarray podporuje ukládání dat (tedy jak n-rozměrných polí s metainformacemi, tak i sady těchto polí) do formátu NetCDF neboli Network Common Data Form. Jedná se o poměrně starý formát, protože práce na na něm začaly již v roce 1988. Tento původní formát se dnes nazývá „classic NetCDF format“ a zajímavé je, že se stále používá (ostatně stále se používá například i grafický formát GIF z roku 1987, resp. jeho nová verze z roku 1989). Čtvrtá verze formátu NetCDF z roku 2008 již přímo zmiňuje formát HDF. NetCDF obsahuje hlavičku za níž následují jednotlivá pole a prakticky libovolné množství záznamů s metadaty o těchto polích ve formě dvojic klíč-hodnota. V současnosti je tento formát podporován v mnoha ekosystémech, například v ekosystému programovacího jazyka Python, jazyka Julia, v Mathematice, MATLABu atd. (již z tohoto výčtu je patrné, že tento formát je primárně určen pro uložení vědeckých dat).

Uložení objektu typu DataArray do formátu NetCDF je na první pohled snadné, protože postačuje použít metodu DataArray.to_netcdf, které se předá jméno výsledného souboru:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(10, 10)
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y"),
                     coords={"x":xcoords, "y":ycoords},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
array.to_netcdf("temperatures.nc")

Ve skutečnosti je však pro uložení v tomto formátu nezbytné nainstalovat buď balíček netCDF4-Python nebo knihovnu SciPy, která potřebnou funkcionalitu podporuje:

$ pdm add scipy
 
Adding packages to default dependencies: scipy
🔒 Lock successful
Changes are written to pyproject.toml.
Synchronizing working set with resolved packages: 1 to add, 0 to update, 0 to
remove
 
  ✔ Install scipy 1.9.3 successful
 
🎉 All complete!

Výsledkem bude upravený projektový soubor a samozřejmě i všechny nainstalované balíčky:

[project]
name = ""
version = ""
description = ""
authors = [
    {name = "", email = ""},
]
dependencies = [
    "numpy>=1.24.4",
    "xarray>=2023.1.0",
    "scipy>=1.9.3",
]
requires-python = ">=3.8"
readme = "README.md"
license = {text = "MIT"}

Nyní se pokusíme o export. Ten se ovšem nepodaří, neboť atributy ve formátu netCDF4 mohou být jen číselné či řetězcové. Proto si skript nepatrně upravíme do podoby:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(10, 10)
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y"),
                     coords={"x":xcoords, "y":ycoords},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid"))
 
 
print(array)
array.to_netcdf("temperatures.nc")

Nyní již k exportu došlo a vznikl tento soubor:

$ ls -l temperatures.nc
-rw-r--r--. 1 ptisnovs ptisnovs 1356 Oct 28 08:55 temperatures.nc
 
$ file temperatures.nc
temperatures.nc: NetCDF Data Format data (64-bit offset)

Ten je přenositelný i do všech dalších systémů, které formát netCDF podporují.

11. Přečtení koordinát na zvolené ose ve formě nového pole

Samotné koordináty jsou v knihovně xarray velmi důležitým konceptem. Můžeme je kdykoli přečíst selektorem pole.coords[název_dimenze], přičemž výsledkem bude (jak typické) další pole typu DataArray, jehož jméno bude odpovídat jménu zvolené (čtené) osy (tedy dimenze). Ostatně si to můžeme velmi snadno otestovat:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(10, 10, 3)
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
times = ["2023-10-01", "2023-10-02", "2023-10-03"]
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y", "time"),
                     coords={"x":xcoords, "y":ycoords, "time":times},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
print()
 
print(array.coords["x"])
print()
 
print(array.coords["y"])
print()
 
print(array.coords["time"])
print()

Výsledky jsou poměrně dobře čitelné:

<xarray.DataArray 'x' (x: 10)>
array([ 10.,  20.,  30.,  40.,  50.,  60.,  70.,  80.,  90., 100.])
Coordinates:
  * x        (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
 
<xarray.DataArray 'y' (y: 10)>
array([-100.,  -90.,  -80.,  -70.,  -60.,  -50.,  -40.,  -30.,  -20.,  -10.])
Coordinates:
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0
 
<xarray.DataArray 'time' (time: 3)>
array(['2023-10-01', '2023-10-02', '2023-10-03'], dtype='<U10')
Coordinates:
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'

Dokonce je možné použít ještě kratší zápis pole[název_dimenze] (což ovšem může být matoucí – nejedná se o výběr prvku pole):

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(10, 10, 3)
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
times = ["2023-10-01", "2023-10-02", "2023-10-03"]
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y", "time"),
                     coords={"x":xcoords, "y":ycoords, "time":times},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
print()
 
print(array["x"])
print()
 
print(array["y"])
print()
 
print(array["time"])
print()

Výsledky by měly být totožné s předchozím příkladem:

<xarray.DataArray 'x' (x: 10)>
array([ 10.,  20.,  30.,  40.,  50.,  60.,  70.,  80.,  90., 100.])
Coordinates:
  * x        (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
 
<xarray.DataArray 'y' (y: 10)>
array([-100.,  -90.,  -80.,  -70.,  -60.,  -50.,  -40.,  -30.,  -20.,  -10.])
Coordinates:
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0
 
<xarray.DataArray 'time' (time: 3)>
array(['2023-10-01', '2023-10-02', '2023-10-03'], dtype='<U10')
Coordinates:
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'

12. Použití číselných indexů při přístupu k prvkům n-dimenzionálních polí

Podobně jako v knihovně Numpy, i v případě použití xarray lze k prvkům n-dimenzionálních polí přistupovat přes celočíselné indexy, čímž se vlastně obchází koncept dimenzí a koordinát. Podívejme se na příklad trojrozměrného pole o rozměrech 10×10×3 prvky. Použijeme tři typy celočíselných indexů:

import numpy as np
import xarray as xr
 
temperatures = np.arange(0, 300).reshape((10, 10, 3))
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
times = ["2023-10-01", "2023-10-02", "2023-10-03"]
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y", "time"),
                     coords={"x":xcoords, "y":ycoords, "time":times},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
print()
 
print(array[0])
print()
 
print(array[0][2])
print()
 
print(array[:,2])
print()

Výsledná pole (protože výsledkem jsou buď skaláry nebo pole):

array[0] - získání 2D matice z 3D pole
<xarray.DataArray 'Temperature measurement' (y: 10, time: 3)>
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14],
       [15, 16, 17],
       [18, 19, 20],
       [21, 22, 23],
       [24, 25, 26],
       [27, 28, 29]])
Coordinates:
    x        float64 10.0
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
 
 
 
array[0][2] - získání 1D vektoru z 3D pole (sloupec časů)
<xarray.DataArray 'Temperature measurement' (time: 3)>
array([6, 7, 8])
Coordinates:
    x        float64 10.0
    y        float64 -80.0
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
 
 
 
array[:,2] - získání 2D matice z 3D pole (jiný typ řezu)
<xarray.DataArray 'Temperature measurement' (x: 10, time: 3)>
array([[  6,   7,   8],
       [ 36,  37,  38],
       [ 66,  67,  68],
       [ 96,  97,  98],
       [126, 127, 128],
       [156, 157, 158],
       [186, 187, 188],
       [216, 217, 218],
       [246, 247, 248],
       [276, 277, 278]])
Coordinates:
  * x        (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
    y        float64 -80.0
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...

13. Využití operací isel a sel při přístupu k prvkům n-dimenzionálních polí

K prvkům n-dimenzionálních polí (což jsou buď přímo skalární prvky, vektory, matice nebo další pole) lze ovšem přistupovat i dalšími způsoby. Knihovna Xarray v tomto ohledu nabízí především operaci nazvanou isel, která umožňuje specifikovat osu (její název) a současně i index (nikoli souřadnici!) na této ose. To je mnohdy mnohem čitelnější, než použití pozičních argumentů. Ostatně si to můžeme velmi snadno otestovat:

print(array.isel(x=4))
print()
 
print(array.isel(y=4))
print()

Ještě užitečnější je specifikace osy a souřadnice na této ose (tedy nikoli indexu). Pro tento účel je určena operace nazvaná sel:

print(array.sel(time="2023-10-02"))
print()

Výsledkem výběru je opět datová struktura DataArray, což nám umožňuje navázání většího množství výběrových operací:

print(array.sel(time="2023-10-02").isel(x=0))
print()
 
print(array.sel(time="2023-10-02").isel(x=0).isel(y=0))
print()

Vše si vyzkoušíme na následujícím příkladu s trojrozměrným polem:

import numpy as np
import xarray as xr
 
temperatures = np.arange(0, 300).reshape((10, 10, 3))
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
times = ["2023-10-01", "2023-10-02", "2023-10-03"]
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y", "time"),
                     coords={"x":xcoords, "y":ycoords, "time":times},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
print()
 
print(array.isel(x=4))
print()
 
print(array.isel(y=4))
print()
 
print(array.sel(time="2023-10-02"))
print()
 
print(array.sel(time="2023-10-02").isel(x=0))
print()
 
print(array.sel(time="2023-10-02").isel(x=0).isel(y=0))
print()

Výsledky všech pěti výběrů z původního pole:

print(array.isel(x=4))
 
 
 
<xarray.DataArray 'Temperature measurement' (y: 10, time: 3)>
array([[120, 121, 122],
       [123, 124, 125],
       [126, 127, 128],
       [129, 130, 131],
       [132, 133, 134],
       [135, 136, 137],
       [138, 139, 140],
       [141, 142, 143],
       [144, 145, 146],
       [147, 148, 149]])
Coordinates:
    x        float64 50.0
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
print(array.isel(y=4))
 
 
 
<xarray.DataArray 'Temperature measurement' (x: 10, time: 3)>
array([[ 12,  13,  14],
       [ 42,  43,  44],
       [ 72,  73,  74],
       [102, 103, 104],
       [132, 133, 134],
       [162, 163, 164],
       [192, 193, 194],
       [222, 223, 224],
       [252, 253, 254],
       [282, 283, 284]])
Coordinates:
  * x        (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
    y        float64 -60.0
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
print(array.sel(time="2023-10-02"))
 
 
 
<xarray.DataArray 'Temperature measurement' (x: 10, y: 10)>
array([[  1,   4,   7,  10,  13,  16,  19,  22,  25,  28],
       [ 31,  34,  37,  40,  43,  46,  49,  52,  55,  58],
       [ 61,  64,  67,  70,  73,  76,  79,  82,  85,  88],
       [ 91,  94,  97, 100, 103, 106, 109, 112, 115, 118],
       [121, 124, 127, 130, 133, 136, 139, 142, 145, 148],
       [151, 154, 157, 160, 163, 166, 169, 172, 175, 178],
       [181, 184, 187, 190, 193, 196, 199, 202, 205, 208],
       [211, 214, 217, 220, 223, 226, 229, 232, 235, 238],
       [241, 244, 247, 250, 253, 256, 259, 262, 265, 268],
       [271, 274, 277, 280, 283, 286, 289, 292, 295, 298]])
Coordinates:
  * x        (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0
    time     <U10 '2023-10-02'
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
print(array.sel(time="2023-10-02").isel(x=0))
 
 
 
<xarray.DataArray 'Temperature measurement' (y: 10)>
array([ 1,  4,  7, 10, 13, 16, 19, 22, 25, 28])
Coordinates:
    x        float64 10.0
  * y        (y) float64 -100.0 -90.0 -80.0 -70.0 ... -40.0 -30.0 -20.0 -10.0
    time     <U10 '2023-10-02'
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
print(array.sel(time="2023-10-02").isel(x=0).isel(y=0))
 
 
 
<xarray.DataArray 'Temperature measurement' ()>
array(1)
Coordinates:
    x        float64 10.0
    y        float64 -100.0
    time     <U10 '2023-10-02'
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
Poznámka: povšimněte si, že se stále zachovávají všechny relevantní metainformace získané z původního pole!

14. Základní aritmetické a relační operace s polem (broadcasting)

V knihovně NumPy je implementována podpora pro provádění operací nad celými poli (součet, rozdíl) a taktéž podpora pro takzvaný broadcasting, tedy pro rozšíření pole s menší dimenzí tak, aby bylo možné zvolenou operaci provést (tedy limitně lze přičíst skalár ke každému prvku libovolného N-rozměrného pole). Tato podpora je přidána i do knihovny Xarray, což si opět můžeme velmi snadno otestovat a zjistit, do jaké míry budou výsledky odpovídat očekávání. Provedeme postupně změnu znaménka všech prvků pole, vynásobení všech prvků pole skalárem a nakonec zaokrouhlení všech prvků vstupního pole:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(5, 5)
 
xcoords = np.linspace(10, 100, 5)
ycoords = np.linspace(-100, -10, 5)
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y"),
                     coords={"x":xcoords, "y":ycoords},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
print()
 
print(-array)
print()
 
print(array * 2)
print()
 
print(array.round())
print()

Vypočtené výsledky:

print(array)
 
 
 
<xarray.DataArray 'Temperature measurement' (x: 5, y: 5)>
array([[24.0898683 ,  5.73595219, 28.81478359,  7.86339653, 18.6217371 ],
       [17.57468852, -0.39366504, -0.42952136,  1.30559859, -0.12386281],
       [-2.20172524, 21.12189613, 13.50420003, 14.56997888, 29.93619462],
       [-4.07788389, -2.99061956, 19.7810614 , 15.83607309, 14.84566202],
       [ 4.07018656, 24.21400408, -1.86752453, -2.01035754, 26.85957395]])
Coordinates:
  * x        (x) float64 10.0 32.5 55.0 77.5 100.0
  * y        (y) float64 -100.0 -77.5 -55.0 -32.5 -10.0
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
print(-array)
 
 
 
<xarray.DataArray 'Temperature measurement' (x: 5, y: 5)>
array([[-24.0898683 ,  -5.73595219, -28.81478359,  -7.86339653,
        -18.6217371 ],
       [-17.57468852,   0.39366504,   0.42952136,  -1.30559859,
          0.12386281],
       [  2.20172524, -21.12189613, -13.50420003, -14.56997888,
        -29.93619462],
       [  4.07788389,   2.99061956, -19.7810614 , -15.83607309,
        -14.84566202],
       [ -4.07018656, -24.21400408,   1.86752453,   2.01035754,
        -26.85957395]])
Coordinates:
  * x        (x) float64 10.0 32.5 55.0 77.5 100.0
  * y        (y) float64 -100.0 -77.5 -55.0 -32.5 -10.0
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
print(array * 2)
 
 
 
<xarray.DataArray 'Temperature measurement' (x: 5, y: 5)>
array([[48.1797366 , 11.47190438, 57.62956718, 15.72679306, 37.2434742 ],
       [35.14937704, -0.78733008, -0.85904272,  2.61119719, -0.24772562],
       [-4.40345048, 42.24379226, 27.00840006, 29.13995776, 59.87238924],
       [-8.15576777, -5.98123913, 39.56212279, 31.67214619, 29.69132405],
       [ 8.14037312, 48.42800817, -3.73504907, -4.02071507, 53.71914789]])
Coordinates:
  * x        (x) float64 10.0 32.5 55.0 77.5 100.0
  * y        (y) float64 -100.0 -77.5 -55.0 -32.5 -10.0
print(array.round())
 
 
 
<xarray.DataArray 'Temperature measurement' (x: 5, y: 5)>
array([[24.,  6., 29.,  8., 19.],
       [18., -0., -0.,  1., -0.],
       [-2., 21., 14., 15., 30.],
       [-4., -3., 20., 16., 15.],
       [ 4., 24., -2., -2., 27.]])
Coordinates:
  * x        (x) float64 10.0 32.5 55.0 77.5 100.0
  * y        (y) float64 -100.0 -77.5 -55.0 -32.5 -10.0
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
Poznámka: povšimněte si, že výsledkem je nové pole, které má stejné atributy a metadata, jako pole původní.

Podporovány jsou i relační operace. V následujícím demonstračním příkladu je proveden broadcasting operace porovnání hodnoty každého prvku s nulou:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(5, 5)
 
xcoords = np.linspace(10, 100, 5)
ycoords = np.linspace(-100, -10, 5)
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y"),
                     coords={"x":xcoords, "y":ycoords},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
print()
 
print(array >= 0)
původní pole:
 
<xarray.DataArray 'Temperature measurement' (x: 5, y: 5)>
array([[22.01427636, 20.07058816, -5.52517483, 27.1273763 , 26.60849883],
       [ 9.64803697, -6.15887599, 18.84069071, -7.4845254 , 17.78351831],
       [24.62328894,  0.85433323, -8.92058503, -2.88662501,  6.82371433],
       [17.61267925, 25.79661576,  9.87869585, -2.3779088 , -2.54645438],
       [15.31556007,  2.24089859, -2.55861374,  4.18911297, -5.9337331 ]])
Coordinates:
  * x        (x) float64 10.0 32.5 55.0 77.5 100.0
  * y        (y) float64 -100.0 -77.5 -55.0 -32.5 -10.0
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
 
 
 
nové pole obsahující pouze pravdivostní hodnoty:
 
<xarray.DataArray 'Temperature measurement' (x: 5, y: 5)>
array([[ True,  True, False,  True,  True],
       [ True, False,  True, False,  True],
       [ True,  True, False, False,  True],
       [ True,  True,  True, False, False],
       [ True,  True, False,  True, False]])
Coordinates:
  * x        (x) float64 10.0 32.5 55.0 77.5 100.0
  * y        (y) float64 -100.0 -77.5 -55.0 -32.5 -10.0

15. Konverze pole operací where

Operace where umožňuje konvertovat jedno pole na pole jiné na základě zapsané podmínky. Snadno například můžeme zkonvertovat 2D pole s naměřenými teplotami na jiné pole, v němž budou zapsány pouze informace o tom, zda je teplota pod bodem nebo nad bodem mrazu:

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(5, 5)
 
xcoords = np.linspace(10, 100, 5)
ycoords = np.linspace(-100, -10, 5)
 
array = xr.DataArray(temperatures,
                     name="Temperature measurement",
                     dims=("x", "y"),
                     coords={"x":xcoords, "y":ycoords},
                     attrs=dict(
                         units = "centigrees",
                         description ="Local temperature values measured in grid",
                         measured_by = {"name": "ThermometerBot",
                              "vendor": "BIY",
                              "version": (1, 0, 0)}
                         ))
 
 
print(array)
print()
 
print(xr.where(array <= 0, "freezing", "above 0°C"))

Po spuštění tohoto skriptu se nejdříve vypíše původní pole a posléze pole obsahující pouze prvky se dvěma možnými hodnotami (mrzne, teplota nad bodem mrazu):

<xarray.DataArray 'Temperature measurement' (x: 5, y: 5)>
array([[ 5.09135141, 14.87737191, 26.92786592, 19.53857612,  1.99129423],
       [-5.40843065, 20.34764162, 17.73095444, -4.79341295, 15.15640546],
       [ 5.01924974,  4.57123972, 24.84870027, 24.26450989, -2.46815504],
       [-6.95834721, -3.89831812, 22.64776767, 10.0516584 , 20.16149552],
       [12.52627837, 23.93366452, 25.61122643, -8.34828794, 20.23273152]])
Coordinates:
  * x        (x) float64 10.0 32.5 55.0 77.5 100.0
  * y        (y) float64 -100.0 -77.5 -55.0 -32.5 -10.0
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
 
<xarray.DataArray 'Temperature measurement' (x: 5, y: 5)>
array([['above 0°C', 'above 0°C', 'above 0°C', 'above 0°C', 'above 0°C'],
       ['freezing', 'above 0°C', 'above 0°C', 'freezing', 'above 0°C'],
       ['above 0°C', 'above 0°C', 'above 0°C', 'above 0°C', 'freezing'],
       ['freezing', 'freezing', 'above 0°C', 'above 0°C', 'above 0°C'],
       ['above 0°C', 'above 0°C', 'above 0°C', 'freezing', 'above 0°C']],
      dtype='<U9')
Coordinates:
  * x        (x) float64 10.0 32.5 55.0 77.5 100.0
  * y        (y) float64 -100.0 -77.5 -55.0 -32.5 -10.0
Poznámka: povšimněte si, že i ve druhém případě se stále pracuje s typem DataArray.

16. Množina polí: datový typ DataSet

Datový typ DataSet umožňuje uložení většího množství polí do jediné datové struktury s tím, že tato pole mohou sdílet stejné osy (dimenze) a koordináty:

Obrázek 2: Vztah mezi poli, jejich počtem dimenzí a osami (dimenzemi) v DataSetu.

Prozatím si ukažme velmi jednoduchý příklad, v němž bude množina polí obsahovat dvě pole s teplotami a rychlostí větru (obě pole jsou, na rozdíl od obrázku, jen dvoudimenzionální):

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(10, 10)
wind = 100*np.random.rand(10, 10)
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
dataset = xr.Dataset({"temperatures": (["x", "y"], temperatures),
                      "wind": (["x", "y"], wind)},
                       coords={"x":xcoords, "y":ycoords})
 
print(dataset)

DataSet se zobrazí takto:

Dimensions:       (x: 10, y: 10)
Coordinates:
  * x             (x) float64 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0 100.0
  * y             (y) float64 -100.0 -90.0 -80.0 -70.0 ... -30.0 -20.0 -10.0
Data variables:
    temperatures  (x, y) float64 -6.135 -4.41 5.464 14.3 ... 16.53 -4.616 -2.667
    wind          (x, y) float64 31.51 4.919 50.45 52.2 ... 23.57 62.56 89.88

Shodné rozměry polí se při konstrukci datasetu kontrolují (protože se sdílí koordináty):

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(10, 10)
wind = 100*np.random.rand(20, 20)
 
xcoords = np.linspace(10, 100, 10)
ycoords = np.linspace(-100, -10, 10)
 
dataset = xr.Dataset({"temperatures": (["x", "y"], temperatures),
                      "wind": (["x", "y"], wind)},
                       coords={"x":xcoords, "y":ycoords})
 
print(dataset)

V tomto případě je vyhozena výjimka informující o rozdílných rozměrech polí:

ValueError: conflicting sizes for dimension 'x': length 20 on 'wind' and length 10 on {'x': 'temperatures', 'y': 'temperatures'}

17. Dataset s dvojicí trojrozměrných polí

V dalším demonstračním příkladu je ukázána konstrukce Datasetu s dvojicí trojrozměrných polí. První pole obsahuje teploty změřené v mřížce v určitém časovém intervalu, druhé pole pak obsahuje sílu větru. Obě pole sdílí osy (dimenze) i souřadnice na nich (koordináty):

import numpy as np
import xarray as xr
 
temperatures = -10 + 40*np.random.rand(2, 2, 3)
wind = 100*np.random.rand(2, 2, 3)
 
longitudes = [[-99.83, -99.32], [-99.79, -99.23]]
latitudes = [[42.25, 42.21], [42.63, 42.59]]
times = ["2023-10-01", "2023-10-02", "2023-10-03"]
 
dataset = xr.Dataset({"temperatures": (["x", "y", "time"], temperatures),
                      "wind": (["x", "y", "time"], wind)},
                      coords={
                          "lon": (["x", "y"], longitudes),
                          "lat": (["x", "y"], latitudes),
                          "time": times})
 
 
print(dataset)
 
print()
print("Temperatures:")
print(dataset["temperatures"])
 
print()
print("Wind:")
print(dataset["wind"])

Po spuštění tohoto skriptu se zobrazí jak celý původní dataset, tak i jednotlivá pole, která z něho byla přečtena:

<xarray.Dataset>
Dimensions:       (x: 2, y: 2, time: 3)
Coordinates:
    lon           (x, y) float64 -99.83 -99.32 -99.79 -99.23
    lat           (x, y) float64 42.25 42.21 42.63 42.59
  * time          (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Dimensions without coordinates: x, y
Data variables:
    temperatures  (x, y, time) float64 24.16 -1.54 0.6033 ... 26.13 23.31 -6.954
    wind          (x, y, time) float64 62.01 67.12 43.23 ... 49.47 20.94 62.97
 
Temperatures:
<xarray.DataArray 'temperatures' (x: 2, y: 2, time: 3)>
array([[[24.16258661, -1.53957247,  0.60330884],
        [18.93054758, 24.08112626, -2.11897159]],

       [[27.1337761 ,  1.59080802, -5.46317688],
        [26.13170764, 23.30735881, -6.95440354]]])
Coordinates:
    lon      (x, y) float64 -99.83 -99.32 -99.79 -99.23
    lat      (x, y) float64 42.25 42.21 42.63 42.59
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Dimensions without coordinates: x, y
 
Wind:
<xarray.DataArray 'wind' (x: 2, y: 2, time: 3)>
array([[[62.01079346, 67.11864438, 43.22516902],
        [19.36766203, 48.18517828, 39.55293065]],

       [[88.02526604,  6.9555846 , 13.95148965],
        [49.46957983, 20.93642261, 62.97467643]]])
Coordinates:
    lon      (x, y) float64 -99.83 -99.32 -99.79 -99.23
    lat      (x, y) float64 42.25 42.21 42.63 42.59
  * time     (time) <U10 '2023-10-01' '2023-10-02' '2023-10-03'
Dimensions without coordinates: x, y

18. Operace nad poli s odlišnou souřadnou mřížkou

Jednou z nejužitečnějších vlastností knihovny Xarray je zajištění, že pokud bude nějaká operace (například součet) probíhat nad dvěma poli s odlišnou souřadnou mřížkou, bude operace provedena takovým způsobem, aby se sčítaly prvky se shodnými souřadnicemi. Výsledné pole bude mít obecně menší rozměry, než obě pole vstupní, protože ty prvky polí, které nemají odpovídající protějšek ve druhém poli, nebudou přidány do výsledku.

Tuto vlastnost si můžeme ukázat na součtu dvou dvourozměrných polí (tedy vlastně matic). První pole obsahuje prvky v mřížce 1–10×1–10 (představte si tedy šachovnici se sloupci 1, 2, … 10 a řádky 1, 2, …10), druhé pole prvky v mřížce 6–15×6–15. Výsledkem bude pole s prvky ležícími v mřížce 6–10×6–10, což je vlastně jen jedna čtvrtina velikosti původních polí (25 prvků vs. 100 prvků):

bitcoin školení listopad 24

import numpy as np
import xarray as xr
 
temperatures1 = np.arange(100).reshape(10, 10)
temperatures2 = np.array([100]*100).reshape(10, 10)
 
xcoords1 = np.linspace(1, 10, 10)
ycoords1 = np.linspace(1, 10, 10)
 
print("Coordinates for 1st DataArray")
print("x:", xcoords1)
print("y:", ycoords1)
print()
 
xcoords2 = np.linspace(6, 15, 10)
ycoords2 = np.linspace(6, 15, 10)
 
print("Coordinates for 2nd DataArray")
print("x:", xcoords2)
print("y:", ycoords2)
print()
 
array1 = xr.DataArray(temperatures1,
                      name="Temperature measurement #1",
                      dims=("x", "y"),
                      coords={"x":xcoords1, "y":ycoords1},
                      attrs=dict(
                          units = "centigrees",
                          description ="Local temperature values measured in grid #1",
                          measured_by = {"name": "ThermometerBot",
                               "vendor": "BIY",
                               "version": (1, 0, 0)}
                          ))
 
 
array2 = xr.DataArray(temperatures2,
                      name="Temperature measurement #2",
                      dims=("x", "y"),
                      coords={"x":xcoords2, "y":ycoords2},
                      attrs=dict(
                          units = "centigrees",
                          description ="Local temperature values measured in grid #2",
                          measured_by = {"name": "ThermometerBot",
                               "vendor": "BIY",
                               "version": (1, 0, 0)}
                          ))
 
 
print(array1)
print()
print()
 
print(array2)
print()
print()
 
array3 = array1 + array2
print(array3)
print()
print()

Výsledek získaný po spuštění tohoto demonstračního příkladu:

Coordinates for 1st DataArray
x: [ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]
y: [ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]
 
Coordinates for 2nd DataArray
x: [ 6.  7.  8.  9. 10. 11. 12. 13. 14. 15.]
y: [ 6.  7.  8.  9. 10. 11. 12. 13. 14. 15.]
 
 
 
Array #1:
 
<xarray.DataArray 'Temperature measurement #1' (x: 10, y: 10)>
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
       [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
       [70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
       [80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
       [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
Coordinates:
  * x        (x) float64 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0
  * y        (y) float64 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid #1
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
 
 
 
Array #2:
 
<xarray.DataArray 'Temperature measurement #2' (x: 10, y: 10)>
array([[100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
       [100, 100, 100, 100, 100, 100, 100, 100, 100, 100]])
Coordinates:
  * x        (x) float64 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0
  * y        (y) float64 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0
Attributes:
    units:        centigrees
    description:  Local temperature values measured in grid #2
    measured_by:  {'name': 'ThermometerBot', 'vendor': 'BIY', 'version': (1, ...
 
 
 
Array #1 + Array #2:
 
<xarray.DataArray (x: 5, y: 5)>
array([[155, 156, 157, 158, 159],
       [165, 166, 167, 168, 169],
       [175, 176, 177, 178, 179],
       [185, 186, 187, 188, 189],
       [195, 196, 197, 198, 199]])
Coordinates:
  * x        (x) float64 6.0 7.0 8.0 9.0 10.0
  * y        (y) float64 6.0 7.0 8.0 9.0 10.0

19. Repositář s demonstračními příklady

Všechny Pythonovské skripty, které jsme si ukázali v dnešním článku, naleznete na adrese https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady (pro jejich spuštění je nutné mít nainstalovánu knihovnu xarray a její závislosti, zejména Numpy):

# Příklad Stručný popis Adresa
1 01_help.py vestavěná nápověda k balíčku xarray https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/01_help.py
2 02_raw_xarray.py konstrukce instance typu DataArray https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/02_raw_xa­rray.py
3 03_xarray_metadata.py metadata přidaná k datové struktuře DataArray: specifikace dimenzí https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/03_xa­rray_metadata.py
4 04_xarray_metadata.py metadata přidaná k datové struktuře DataArray: specifikace koordinát pro jednu dimenzi https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/04_xa­rray_metadata.py
5 05_xarray_metadata.py metadata přidaná k datové struktuře DataArray: specifikace koordinát pro dvojici dimenzí https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/05_xa­rray_metadata.py
6 06_xarray_metadata.py metadata přidaná k datové struktuře DataArray: specifikace jména n-dimenzionálního pole https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/06_xa­rray_metadata.py
7 07_xarray_custom_attributes.py přidání vlastních atributů k datové struktuře DataArray https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/07_xa­rray_custom_attributes.py
8 08_xarray_custom_attributes.py přidání vlastních atributů k datové struktuře DataArray https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/08_xa­rray_custom_attributes.py
9 09_multiple_dimensions.py vícedimenzionální pole a jeho atributy (různé koordináty) https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/09_mul­tiple_dimensions.py
10 10_multiple_dimensions.py vícedimenzionální pole a jeho atributy (tři rozměry) https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/10_mul­tiple_dimensions.py
11 11_properties.py přečtení vlastností vícedimenzionálních polí https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/11_pro­perties.py
12 12_netcdf_write.py uložení polí do formátu NetCDF https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/12_net­cdf_write.py
13 13_get_coordinate.py získání zvolených koordinát https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/13_get_co­ordinate.py
14 14_get_coordinate.py získání zvolených koordinát https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/14_get_co­ordinate.py
15 15_get_by_coordinate.py přečtení části pole na základě zadaných koordinát https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/15_get_by_co­ordinate.py
16 16_sel_isel.py výběr prvků pole metodami set a isel https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/16_sel_isel.py
17 17_basic_math.py matematické operace nad celými poli (jako v Numpy) https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/17_ba­sic_math.py
18 18_condition.py podmínka aplikovaná na všechny prvky pole https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/18_con­dition.py
19 19_where.py transformace pole s využitím podmínky where https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/19_where.py
20 21_dataset.py základní použití datového typu Dataset https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/21_dataset.py
21 21_dataset.py kontrola, zda mají pole totožnou velikost https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/21_dataset.py
22 22_dataset.py komplikovanější definice instance datového typu Dataset https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/22_dataset.py
23 23_math_coords.py operace nad poli s odlišnou souřadnou mřížkou https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/23_mat­h_coords.py
24 24_chess.py reprezentace šachovnice https://github.com/tisnik/most-popular-python-libs/blob/master/xarray/24_chess.py

20. Odkazy na Internetu

  1. Xarray documentation
    https://docs.xarray.dev/en/sta­ble/index.html
  2. Xarray na stránkách PyPi
    https://pypi.org/project/xarray/
  3. Xarray tutorial
    https://tutorial.xarray.dev/in­tro.html
  4. Repositář knihovny xarray
    https://github.com/pydata/xarray
  5. A Simple File Format for NumPy Arrays
    https://docs.scipy.org/doc/numpy-1.14.2/neps/npy-format.html
  6. Stránky projektu Numpy
    https://numpy.org/
  7. Stránky projektu Pandas
    https://pandas.pydata.org/
  8. numpy.lib.format
    https://numpy.org/devdocs/re­ference/generated/numpy.lib­.format.html
  9. The NumPy array: a structure for efficient numerical computation
    https://arxiv.org/pdf/1102.1523.pdf
  10. A Gentle Introduction to Pandas Data Analysis (on Kaggle)
    https://www.youtube.com/wat­ch?v=_Eb0utIRdkw&list=PL7RwtdVQXQ8o­YpuIIDWR0SaaSCe8ZeZ7t&index=4
  11. Speed Up Your Pandas Dataframes
    https://www.youtube.com/wat­ch?v=u4_c2LDi4b8&list=PL7RwtdVQXQ8o­YpuIIDWR0SaaSCe8ZeZ7t&index=5
  12. numpy.ndarray.tofile
    https://numpy.org/doc/sta­ble/reference/generated/num­py.ndarray.tofile.html#num­py.ndarray.tofile
  13. numpy.fromfile
    https://numpy.org/doc/sta­ble/reference/generated/num­py.fromfile.html
  14. How to read part of binary file with numpy?
    https://stackoverflow.com/qu­estions/14245094/how-to-read-part-of-binary-file-with-numpy
  15. How to read binary files in Python using NumPy?
    https://stackoverflow.com/qu­estions/39762019/how-to-read-binary-files-in-python-using-numpy
  16. numpy.save
    https://numpy.org/doc/sta­ble/reference/generated/num­py.save.html#numpy.save
  17. numpy.load
    https://numpy.org/doc/sta­ble/reference/generated/num­py.load.html#numpy.load
  18. SciPy
    https://scipy.org/
  19. Načítání a ukládání dat uložených v N-rozměrných polích v jazyku Go
    https://www.root.cz/clanky/nacitani-a-ukladani-dat-ulozenych-v-n-rozmernych-polich-v-jazyku-go/
  20. Network Common Data Form (NetCDF)
    https://www.unidata.ucar.e­du/software/netcdf/
  21. xray: N D Labeled Arrays and Datasets | SciPy 2015 | Stephan Hoyer
    https://www.youtube.com/wat­ch?v=X0pAhJgySxk
  22. Xarray Tutorial | xarray fundamentals (Youtube, přetočte si prvních osm nebo devět minut přípravy)
    https://www.youtube.com/wat­ch?v=a339Q5F48UQ

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.