Vorheriger Artikel
Ich werde die oben eingeführte Datenanalyse mit xarray aus praktischerer Sicht vorstellen.
Seit 2017 ist er Entwicklungsmitglied von pydata xarray. In letzter Zeit bin ich hauptsächlich ein Benutzer, aber ich sende gelegentlich PR für Fehlerbehebungen.
Ich verwende xarray für fast alle Datenanalysen, die ich in meinem Hauptgeschäft durchführe.
Es wird davon ausgegangen, dass Sie über Kenntnisse in Numpy verfügen (Sie können Operationen und Operationen mit np.ndarray ausführen).
In diesem Artikel werde ich das xarray-Datenmodell noch einmal vorstellen und dann die grundlegende Operation der Indizierung diskutieren. Man kann mit Sicherheit sagen, dass diese Indizierung die Essenz von xarray ist.
Danach werde ich concat einführen, die umgekehrte Operation der Indizierung.
Auf dieser Grundlage werde ich bei der Betrachtung der tatsächlichen Datenerstellung vorstellen, welche Art von Datenstruktur verwendet werden sollte, um die Analyse mit xarray zu erleichtern.
Ich werde auch ein wenig über das Speichern und Laden von Daten und die Verarbeitung von Speichermangel mit dask sprechen.
Dieser Artikel wurde mit Google Collaboratory verfasst. Jeder kann ausführen und verfolgen, indem er von [hier] kopiert (https://drive.google.com/file/d/1747FtkVJ3KnOszugTGgnmMPIMLPSFg0N/view?usp=sharing).
Kurz gesagt, xarray ist ** ein mehrdimensionales Array mit Achsen **. Sie können sich das als eine Kombination aus Numpys nd-Array und pandas 'pd.Series vorstellen.
Sobald Sie sich daran gewöhnt haben, ist dies sehr praktisch, da Sie bei der Datenanalyse nicht an Koordinaten denken müssen.
Andererseits wird oft gesagt, dass die Nutzung ein wenig einzigartig ist und die Lernkosten hoch sind. Dieser Artikel zielt darauf ab, diese Lernkosten so weit wie möglich zu senken.
Es gibt zwei Hauptklassen in xarray. Eines ist xarray.DataArray und das andere ist xarray.Dataset. Ich werde sie vorstellen.
Dies entspricht fast dem in Multarimensional Data Analysis Library xarray beschriebenen Inhalt.
xarray.DataArray
Einführung in xarray.DataArray, ein ** mehrdimensionales Array mit Achsen **. Ich werde später erklären, wie ein Objekt erstellt wird, aber zuerst werde ich die Verwendung der Daten in xarray.tutorial erklären.
import numpy as np
import xarray as xr
data = xr.tutorial.open_dataset('air_temperature')['air']
data
<xarray.DataArray 'air' (time: 2920, lat: 25, lon: 53)> [3869000 values with dtype=float32] Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Wobei data
eine 3D xr.DataArray-Instanz ist. Die offizielle Abkürzung für xarray lautet "xr".
Wenn Sie "Daten" anzeigen, sehen Sie eine Zusammenfassung wie oben. Das (Zeit: 2920, Lat: 25, Lon: 53)
in der oberen Zeile repräsentiert den Dimensionsnamen des gespeicherten Arrays und seine Anzahl von Elementen.
Wie Sie sehen können, behandelt xarray ** jede Dimension mit einem Namen ** (in der offiziellen Dokumentation * label * genannt).
Die erste Achse ist die "Zeit" -Achse, die zweite Achse ist die "Lat" -Achse und die dritte Achse ist die "Lon" -Achse. Wenn Sie es so benennen, müssen Sie sich keine Gedanken über die Reihenfolge der Achsen machen.
Zusätzlich werden jeder Achse Koordinatenwerte hinzugefügt. Eine Liste der Koordinaten wird im Abschnitt "Koordinaten" angezeigt. In diesen Daten haben alle Achsen von "Zeit", "Lat", "Lon" Koordinaten.
Sie können auch andere Daten anhängen. Sie befinden sich im Abschnitt "Attribute".
Wie im Abschnitt Indexierung ausführlich beschrieben, ermöglichen die Koordinatenachsen das intuitive Abrufen von Daten im gewünschten Bereich. Wenn Sie beispielsweise die Daten für den 30. August 2014 möchten,
data.sel(time='2014-08-30')
<xarray.DataArray 'air' (time: 4, lat: 25, lon: 53)> array([[[270.29 , 270.29 , ..., 258.9 , 259.5 ], [273. , 273.1 , ..., 262.6 , 264.19998], ..., [299.5 , 298.79 , ..., 299. , 298.5 ], [299.29 , 299.29 , ..., 299.9 , 300. ]], [[269.9 , 270.1 , ..., 258.6 , 259.5 ], [273. , 273.29 , ..., 262.5 , 265. ], ..., [299.19998, 298.9 , ..., 298.5 , 298. ], [299.4 , 299.69998, ..., 299.19998, 299.6 ]], [[270.4 , 270.69998, ..., 261.29 , 261.9 ], [273. , 273.6 , ..., 266.4 , 268.6 ], ..., [297.9 , 297.6 , ..., 298.29 , 298.29 ], [298.69998, 298.69998, ..., 299.1 , 299.4 ]], [[270. , 270.4 , ..., 266. , 266.19998], [273. , 273.9 , ..., 268.1 , 269.69998], ..., [298.5 , 298.29 , ..., 298.69998, 299. ], [299.1 , 299.19998, ..., 299.5 , 299.69998]]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2014-08-30 ... 2014-08-30T18:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Sie können es so machen. Hier wird die Methode ".sel" verwendet, um Daten unter Verwendung der Koordinatenachsen auszuwählen. .sel (time = '2014-08-30')
entspricht der Referenzierung der time
-Achse und der Auswahl der Daten'2014-08-30'
.
DataArray ist auch ein mehrdimensionales Array wie np.ndarray, sodass Sie Operationen wie bei np.ndarray ausführen können.
data * 2
<xarray.DataArray 'air' (time: 2920, lat: 25, lon: 53)> array([[[482.4 , 485. , 487. , ..., 465.59998, 471. , 477.19998], [487.59998, 489. , 489.4 , ..., 465.59998, 470.59998, 478.59998], [500. , 499.59998, 497.78 , ..., 466.4 , 472.78 , 483.4 ], ..., [593.2 , 592.39996, 592.8 , ..., 590.8 , 590.2 , 589.39996], [591.8 , 592.39996, 593.58 , ..., 591.8 , 591.8 , 590.39996], [592.58 , 593.58 , 594.2 , ..., 593.8 , 593.58 , 593.2 ]], [[484.19998, 485.4 , 486.19998, ..., 464. , 467.19998, 471.59998], [487.19998, 488.19998, 488.4 , ..., 462. , 465. , 471.4 ], [506.4 , 505.78 , 504.19998, ..., 461.59998, 466.78 , 477. ], ... [587.38 , 587.77997, 590.77997, ..., 590.18 , 589.38 , 588.58 ], [592.58 , 594.38 , 595.18 , ..., 590.58 , 590.18 , 588.77997], [595.58 , 596.77997, 596.98 , ..., 591.38 , 590.98 , 590.38 ]], [[490.18 , 488.58 , 486.58 , ..., 483.37997, 482.97998, 483.58 ], [499.78 , 498.58 , 496.78 , ..., 479.18 , 480.58 , 483.37997], [525.98 , 524.38 , 522.77997, ..., 479.78 , 485.18 , 492.58 ], ..., [587.58 , 587.38 , 590.18 , ..., 590.58 , 590.18 , 589.38 ], [592.18 , 593.77997, 594.38 , ..., 591.38 , 591.38 , 590.38 ], [595.38 , 596.18 , 596.18 , ..., 592.98 , 592.38 , 591.38 ]]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00
Wie intuitiv sollte es sein, erfolgt die Multiplikation nur mit den Array-Daten und die Achsdaten bleiben unverändert.
Ich erwähnte, dass Sie neben Array-Daten auch Coordinate halten können. Koordinatendaten können wie folgt kategorisiert werden.
Dimension coordinate
Dies wurde im vorherigen Abschnitt als Koordinate eingeführt. Es hat den gleichen Namen wie der Dimensionsname (time
, lon
, lat
in den Daten im vorherigen Abschnitt).
Non-dimension coordinate
Sie können auch Koordinaten mit Namen halten, die sich von der Dimension unterscheiden. Ich werde erklären, in welchen Situationen es notwendig und zweckmäßig ist, aber grundsätzlich sollte verstanden werden, dass es ** beibehalten, aber nicht berechnet ** wird.
Scalar coordinate
Sie können einen Skalar halten, der eine Koordinatenachse sein kann. Dies ist auch ein häufig verwendeter Datentyp, aber vorerst können Sie ihn als nicht dimensionale Koordinate betrachten, die nicht berechnet, sondern beibehalten wird.
Es hat die grundlegenden Methoden in np.ndarray gefunden.
. Shape
: Gibt die Form zurück.size
: Gibt die Gesamtgröße zurück.ndim
: Gibt die Anzahl der Dimensionen zurückAndere,
.sizes
: Gibt ein assoziatives Array von Dimensionsnamen und -größen zurück (Wörterbuchtyp)Sache über Typ
.dtype
: Gibt den Typ des Arrays zurück.astype ()
: Ändert den Typ des Arrays.real
: Gibt den Realteil aller Daten zurück.imag
: Gibt den Imaginärteil aller Daten zurückNp.ndarray wird in DataArray gespeichert. (Als Ergänzung können Sie tatsächlich andere mehrdimensionale Arrays als np.ndarray speichern.)
Sie können mit .data
auf das Inhaltsarray zugreifen.
(Beachten Sie, dass .values
jedes Objekt im Inhalt in np.ndarray konvertiert und zurückgibt.)
type(data.data), data.shape
(numpy.ndarray, (2920, 25, 53))
Koordinatenachsenobjekte können durch Übergeben des Achsnamens in []
wie in einem Wörterbuch abgerufen werden.
data['lat']
<xarray.DataArray 'lat' (lat: 25)> array([75. , 72.5, 70. , 67.5, 65. , 62.5, 60. , 57.5, 55. , 52.5, 50. , 47.5, 45. , 42.5, 40. , 37.5, 35. , 32.5, 30. , 27.5, 25. , 22.5, 20. , 17.5, 15. ], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 Attributes: standard_name: latitude long_name: Latitude units: degrees_north axis: Y
Das abgerufene Objekt ist auch ein DataArray-Objekt.
xarray.Dataset
Ein Dataset ist ein Objekt, das aus mehreren DataArrays besteht.
data = xr.tutorial.open_dataset('air_temperature')
data['mean_temperature'] = data['air'].mean('time')
data
<xarray.Dataset> Dimensions: (lat: 25, lon: 53, time: 2920) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 ... 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 ... 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Data variables: air (time, lat, lon) float32 241.2 242.5 ... 296.19 295.69 mean_temperature (lat, lon) float32 260.37564 260.1826 ... 297.30502 Attributes: Conventions: COARDS title: 4x daily NMC reanalysis (1948) description: Data is from NMC initialized reanalysis\n(4x/day). These a... platform: Model references: http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...
In diesem Beispiel enthält "data" zwei DataArrays, "air" und "mean_temperature". Sie sind im Abschnitt "Datenvariablen" aufgeführt.
air
ist ein dreidimensionales Array mit ( time
, lon
, lat
) Dimensionenmean_temperature
ist ein zweidimensionales Array mit ( lon
, lat
) Dimensionenist.
Die von Ihnen gehaltenen Datenfelder können Achsen gemeinsam nutzen. Daher ist es möglich, mehrere DataArrays gleichzeitig zu indizieren, wie unten gezeigt.
data.sel(lat=70, method='nearest')
<xarray.Dataset> Dimensions: (lon: 53, time: 2920) Coordinates: lat float32 70.0 * lon (lon) float32 200.0 202.5 205.0 ... 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Data variables: air (time, lon) float32 250.0 249.79999 ... 242.59 246.29 mean_temperature (lon) float32 264.7681 264.3271 ... 253.58247 257.71475 Attributes: Conventions: COARDS title: 4x daily NMC reanalysis (1948) description: Data is from NMC initialized reanalysis\n(4x/day). These a... platform: Model references: http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...
Das beibehaltene DataArray kann unterschiedliche Dimensionen haben. Ob die Achsen gemeinsam sind oder nicht, wird durch den Namen der Achse bestimmt. Daher ist es nicht möglich, Koordinatenachsen mit demselben Namen zu haben, obwohl sie nicht üblich sind.
Um ein DataArray aus einem Dataset abzurufen, übergeben Sie einfach den Namen des DataArray als Schlüssel, wie in einem Wörterbuch.
da = data['air']
da
<xarray.DataArray 'air' (time: 2920, lat: 25, lon: 53)> array([[[241.2 , 242.5 , ..., 235.5 , 238.59999], [243.79999, 244.5 , ..., 235.29999, 239.29999], ..., [295.9 , 296.19998, ..., 295.9 , 295.19998], [296.29 , 296.79 , ..., 296.79 , 296.6 ]], [[242.09999, 242.7 , ..., 233.59999, 235.79999], [243.59999, 244.09999, ..., 232.5 , 235.7 ], ..., [296.19998, 296.69998, ..., 295.5 , 295.1 ], [296.29 , 297.19998, ..., 296.4 , 296.6 ]], ..., [[245.79 , 244.79 , ..., 243.98999, 244.79 ], [249.89 , 249.29 , ..., 242.48999, 244.29 ], ..., [296.29 , 297.19 , ..., 295.09 , 294.38998], [297.79 , 298.38998, ..., 295.49 , 295.19 ]], [[245.09 , 244.29 , ..., 241.48999, 241.79 ], [249.89 , 249.29 , ..., 240.29 , 241.68999], ..., [296.09 , 296.88998, ..., 295.69 , 295.19 ], [297.69 , 298.09 , ..., 296.19 , 295.69 ]]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
In diesem Abschnitt wird beschrieben, wie Sie ein DataArray-Objekt erstellen.
Am einfachsten ist es, "np.ndarray" und jeden Achsnamen anzugeben.
xr.DataArray(np.arange(12).reshape(3, 4), dims=['x', 'y'])
<xarray.DataArray (x: 3, y: 4)> array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) Dimensions without coordinates: x, y
Im obigen Beispiel wird ein DataArray mit 3x4-Elementen erstellt. Der Name der ersten Dimension ist "x" und die zweite Dimension ist "y".
Geben Sie das Schlüsselwort "coords" als Wörterbuch an, um die Achsen anzugeben.
xr.DataArray(np.arange(12).reshape(3, 4), dims=['x', 'y'],
coords={'x': [0, 1, 2], 'y': [0.1, 0.2, 0.3, 0.4]})
<xarray.DataArray (x: 3, y: 4)> array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) Coordinates: * x (x) int64 0 1 2 * y (y) float64 0.1 0.2 0.3 0.4
Um eine Nicht-Dimensionskoordinate einzuschließen, müssen Sie den Achsnamen angeben, von dem sie abhängt. Tippen Sie dazu auf das Argument vom Typ Wörterbuch (rechts neben dem Doppelpunkt). Das erste Element ist der Achsname, von dem es abhängt, und das zweite ist der Array-Body.
xr.DataArray(np.arange(12).reshape(3, 4), dims=['x', 'y'],
coords={'x': [0, 1, 2], 'y': [0.1, 0.2, 0.3, 0.4],
'z': ('x', ['a', 'b', 'c'])})
<xarray.DataArray (x: 3, y: 4)> array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) Coordinates: * x (x) int64 0 1 2 * y (y) float64 0.1 0.2 0.3 0.4 z (x) <U1 'a' 'b' 'c'
Wobei die nicht dimensionale Koordinate "z" auf der "x" -Achse definiert ist.
Übergeben Sie die Skalarkoordinate auch an "Koordinaten".
xr.DataArray(np.arange(12).reshape(3, 4), dims=['x', 'y'],
coords={'x': [0, 1, 2], 'y': [0.1, 0.2, 0.3, 0.4], 'scalar': 3})
<xarray.DataArray (x: 3, y: 4)> array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) Coordinates: * x (x) int64 0 1 2 * y (y) float64 0.1 0.2 0.3 0.4 scalar int64 3
Sie können sehen, dass die Skalarkoordinate zu keiner Dimension gehört.
Zusätzlich zu den Achseninformationen können Sie auch den Namen des Attributs oder DataArray übergeben. Attribute gehen jedoch während des Vorgangs verloren. Daher ist es möglicherweise besser, Dinge, die Sie speichern möchten, sofort in einer Datei abzulegen.
Ich werde dies im Kapitel über die Datenstruktur für die Speicherung erläutern, das später erläutert wird.
Die Indizierung ist die grundlegendste und wesentlichste Operation. Es ist keine Übertreibung zu sagen, dass die Entwicklung von xarray begonnen hat, es zu vereinfachen.
xarray ermöglicht die positionsbasierte Indizierung und die achsenbasierte Indizierung.
.isel
Dies ähnelt der Indizierung für gängige Arrays wie np.ndarray. Geben Sie eine Ganzzahl als Argument in Klammern an, z. B. "data [i, j, k]". Das Argument gibt die Position des Elements im ** Array ** an.
da[0, :4, 3]
<xarray.DataArray 'air' (lat: 4)> array([244. , 244.2 , 247.5 , 266.69998], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 lon float32 207.5 time datetime64[ns] 2013-01-01 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Bei der obigen Notation müssen Sie sich die Position jeder Dimension merken (z. B. ist die Zeitachse die allererste Achse).
Es ist überraschend schwierig, sich bei jeder Analyse daran zu erinnern. Wenn Sie es so schreiben, müssen Sie sich nur den Namen der Achse merken.
da.isel(time=0, lat=slice(0, 4), lon=3)
<xarray.DataArray 'air' (lat: 4)> array([244. , 244.2 , 247.5 , 266.69998], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 lon float32 207.5 time datetime64[ns] 2013-01-01 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Fügen Sie auf diese Weise den Achsnamen im Schlüsselwortformat in das Argument der Methode .isel () ein und geben Sie den entsprechenden Index nach dem Gleichwert an.
Beachten Sie, dass Sie beim Angeben eines Bereichs explizit Slices (Slice (0, 4)
) verwenden müssen.
.sel
Bei der tatsächlichen Datenanalyse wird der interessierende Bereich häufig durch Koordinaten angegeben. Dies kann mit xarray mit der Methode .sel erreicht werden.
da.sel(time='2013-01-01', lat=slice(75, 60))
<xarray.DataArray 'air' (time: 4, lat: 7, lon: 53)> array([[[241.2 , 242.5 , ..., 235.5 , 238.59999], [243.79999, 244.5 , ..., 235.29999, 239.29999], ..., [272.1 , 270.9 , ..., 275.4 , 274.19998], [273.69998, 273.6 , ..., 274.19998, 275.1 ]], [[242.09999, 242.7 , ..., 233.59999, 235.79999], [243.59999, 244.09999, ..., 232.5 , 235.7 ], ..., [269.19998, 268.5 , ..., 275.5 , 274.69998], [272.1 , 272.69998, ..., 275.79 , 276.19998]], [[242.29999, 242.2 , ..., 236.09999, 238.7 ], [244.59999, 244.39 , ..., 232. , 235.7 ], ..., [273. , 273.5 , ..., 275.29 , 274.29 ], [275.5 , 275.9 , ..., 277.4 , 277.6 ]], [[241.89 , 241.79999, ..., 235.5 , 237.59999], [246.29999, 245.29999, ..., 231.5 , 234.5 ], ..., [273.29 , 272.6 , ..., 277.6 , 276.9 ], [274.1 , 274. , ..., 279.1 , 279.9 ]]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 62.5 60.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2013-01-01T18:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Geben Sie dem Schlüsselwort wie bei ".isel" den Achsnamen und den gewünschten Koordinatenwert nach dem Gleichwert. Sie können auch das Slice-Objekt verwenden. In diesem Fall können Sie das Argument "Slice" mit einer reellen Zahl versehen.
Es gibt jedoch einige Einschränkungen bei der Methode ".sel".
Die .sel
Methode hat die Optionen Methode
, Toleranz
.
Ich denke, die am häufigsten verwendete "Methode" ist "am nächsten". Es wird mit dem nächstgelegenen Koordinatenwert indiziert.
da.sel(lat=76, method='nearest')
<xarray.DataArray 'air' (time: 2920, lon: 53)> array([[241.2 , 242.5 , 243.5 , ..., 232.79999, 235.5 , 238.59999], [242.09999, 242.7 , 243.09999, ..., 232. , 233.59999, 235.79999], [242.29999, 242.2 , 242.29999, ..., 234.29999, 236.09999, 238.7 ], ..., [243.48999, 242.98999, 242.09 , ..., 244.18999, 244.48999, 244.89 ], [245.79 , 244.79 , 243.48999, ..., 243.29 , 243.98999, 244.79 ], [245.09 , 244.29 , 243.29 , ..., 241.68999, 241.48999, 241.79 ]], dtype=float32) Coordinates: lat float32 75.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Koordinatenachsen haben einen Freiheitsgrad, sodass Sie sie möglicherweise nicht gut indizieren können. Beispielsweise gelten die folgenden Fälle.
Sie können nach dieser Achse mit der Methode "sortby" sortieren, z. B. "da.sortby (" lat ")".
Mit der Methode "isnull", die Koordinaten zurückgibt, die nicht "Nan" sind, wie z. B. "da.isel (lat = ~ da [" lat "]. Isnull ())", können Sie ein Array erstellen, das diese Koordinatenwerte überspringt. Masu
Mit da.isel (lat = np.unique (da ['lat'], return_index = True) [1])
können Sie ein Array erstellen, das den Teil überspringt, der den doppelten Koordinaten entspricht.
.interp
Interpolation ist mit der gleichen Syntax wie Indizierung möglich.
da.interp(lat=74)
<xarray.DataArray 'air' (time: 2920, lon: 53)> array([[242.23999321, 243.29999998, 243.9799988 , ..., 232.79998779, 235.41999512, 238.87998962], [242.69999081, 243.25999451, 243.53999329, ..., 231.60000001, 233.1599945 , 235.75999145], [243.21998903, 243.07599789, 242.97999266, ..., 232.69998783, 234.45999444, 237.49999702], ..., [245.72999275, 245.38999009, 244.68999648, ..., 242.74999088, 243.20999146, 244.00999451], [247.42999566, 246.58999336, 245.48999023, ..., 242.4899933 , 243.38999027, 244.58999329], [247.00999749, 246.28999329, 245.32999587, ..., 240.84999084, 241.00999144, 241.74999085]]) Coordinates: * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 lat int64 74 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
xr.where
Es gibt Zeiten, in denen Sie nur Daten auswählen möchten, die komplexe Bedingungen erfüllen. Zum Beispiel im obigen Beispiel
Oder so.
Wenn das Auswahlergebnis eindimensional ist, beispielsweise wenn ein bestimmter Tag ausgewählt wird, kann es realisiert werden, indem ein eindimensionales Array vom Typ Bool an die Methode ".isel" übergeben wird.
import datetime
#Wähle nur Wochenenden
is_weekend = da['time'].dt.dayofweek.isin([5, 6])
is_weekend
<xarray.DataArray 'dayofweek' (time: 2920)> array([False, False, False, ..., False, False, False]) Coordinates: * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00
#Bool-Typ.Übergeben Sie es an die isel-Methode.
da.isel(time=is_weekend)
<xarray.DataArray 'air' (time: 832, lat: 25, lon: 53)> array([[[248.59999, 246.89 , ..., 245.7 , 246.7 ], [256.69998, 254.59999, ..., 248. , 250.09999], ..., [296.69998, 296. , ..., 295. , 294.9 ], [297. , 296.9 , ..., 296.79 , 296.69998]], [[245.09999, 243.59999, ..., 249.89 , 251.39 ], [254. , 251.79999, ..., 247.79999, 250.89 ], ..., [296.79 , 296.19998, ..., 294.6 , 294.69998], [297.19998, 296.69998, ..., 296.29 , 296.6 ]], ..., [[242.39 , 241.79999, ..., 247.59999, 247.29999], [247.18999, 246.09999, ..., 253.29999, 254.29999], ..., [294.79 , 295.29 , ..., 297.69998, 297.6 ], [296.38998, 297.19998, ..., 298.19998, 298.29 ]], [[249.18999, 248. , ..., 244.09999, 242.5 ], [254.5 , 253. , ..., 251. , 250.59999], ..., [294.88998, 295.19998, ..., 298. , 297.29 ], [296.1 , 296.88998, ..., 298.5 , 298.29 ]]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-05 ... 2014-12-28T18:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Wenn Sie eine Auswahl basierend auf den Daten eines mehrdimensionalen Arrays treffen möchten, können Sie die Form des Arrays nach der Auswahl nicht definieren. Daher empfiehlt es sich, die nicht ausgewählten Elemente durch Nan zu ersetzen. In diesem Fall können Sie die Funktion "where" verwenden.
da.where(da > 270)
<xarray.DataArray 'air' (time: 2920, lat: 25, lon: 53)> array([[[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ..., [296.6 , 296.19998, 296.4 , ..., 295.4 , 295.1 , 294.69998], [295.9 , 296.19998, 296.79 , ..., 295.9 , 295.9 , 295.19998], [296.29 , 296.79 , 297.1 , ..., 296.9 , 296.79 , 296.6 ]], [[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ... [293.69 , 293.88998, 295.38998, ..., 295.09 , 294.69 , 294.29 ], [296.29 , 297.19 , 297.59 , ..., 295.29 , 295.09 , 294.38998], [297.79 , 298.38998, 298.49 , ..., 295.69 , 295.49 , 295.19 ]], [[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ..., [293.79 , 293.69 , 295.09 , ..., 295.29 , 295.09 , 294.69 ], [296.09 , 296.88998, 297.19 , ..., 295.69 , 295.69 , 295.19 ], [297.69 , 298.09 , 298.09 , ..., 296.49 , 296.19 , 295.69 ]]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Hier ersetzen wir die Elemente, die nicht für "da> 270" gelten, durch "np.nan".
Bisher haben wir die grundlegende Indizierung eingeführt, aber xarray ermöglicht auch die erweiterte Indizierung.
Wie in dieser Abbildung gezeigt, können Sie ein anderes Array aus dem mehrdimensionalen Array ausschneiden. Im offiziellen Dokument heißt es Erweiterte Indizierung.
Definieren Sie dazu das als Argument übergebene Array als DataArray. Legen Sie zu diesem Zeitpunkt die Abmessungen dieser Arrays auf die Abmessungen des neu erstellten Arrays fest.
Gemäß der obigen Abbildung ist die neue Dimension "z". Definieren Sie also ein DataArray auf "z".
lon_new = xr.DataArray([60, 61, 62], dims=['z'], coords={'z': ['a', 'b', 'c']})
lat_new = xr.DataArray([16, 46, 76], dims=['z'], coords={'z': ['a', 'b', 'c']})
Wenn Sie diese als Argumente an die Methode ".sel" übergeben, ist "(lon, lat)" [(60, 16), (61, 46), (62, 76)] "(am nächsten). Wird wählen.
da.sel(lon=lon_new, lat=lat_new, method='nearest')
<xarray.DataArray 'air' (time: 2920, z: 3)> array([[296.29 , 280. , 241.2 ], [296.29 , 279.19998, 242.09999], [296.4 , 278.6 , 242.29999], ..., [298.19 , 279.99 , 243.48999], [297.79 , 279.69 , 245.79 ], [297.69 , 279.79 , 245.09 ]], dtype=float32) Coordinates: lat (z) float32 15.0 45.0 75.0 lon (z) float32 200.0 200.0 200.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 * z (z) <U1 'a' 'b' 'c' Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Sie können sehen, dass die neu erhaltene Sequenz nicht mehr von den "lon" -, "lat" -Achsen abhängt, sondern vom "z".
Ein ähnliches Verfahren kann auch für die Interpolation verwendet werden.
da.interp(lon=lon_new, lat=lat_new)
<xarray.DataArray 'air' (time: 2920, z: 3)> array([[nan, nan, nan], [nan, nan, nan], [nan, nan, nan], ..., [nan, nan, nan], [nan, nan, nan], [nan, nan, nan]]) Coordinates: * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 lon (z) int64 60 61 62 lat (z) int64 16 46 76 * z (z) <U1 'a' 'b' 'c' Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Oft möchten Sie mehrere Röntgenobjekte kombinieren. Zum Beispiel, wenn Sie experimentelle Daten und Simulationsdaten analysieren möchten, die mit verschiedenen Parametern zusammen erhalten wurden.
Dies entspricht "np.concatenate", "np.stack". Ich denke, es ist leicht zu verstehen, wenn Sie es als die umgekehrte Operation der Indizierung betrachten.
Die Syntax lautet
xr.concat([data1, data2, ..., ], dim='dim')
ist. Übergeben Sie mehrere DataArrays (oder Datasets) als erstes Argument. Das zweite Argument ist die Richtung des Joins. Abhängig von der Verbindungsrichtung kann es in Verkettungs- und Stapeloperationen unterteilt werden.
Die Grundoperation der Funktion "xr.concat" besteht darin, mehrere DataArrays entlang der vorhandenen Achse zu verbinden.
Zum Beispiel die folgenden zwei DataArray
da0 = da.isel(time=slice(0, 10))
da1 = da.isel(time=slice(10, None))
da0
<xarray.DataArray 'air' (time: 10, lat: 25, lon: 53)> array([[[241.2 , 242.5 , ..., 235.5 , 238.59999], [243.79999, 244.5 , ..., 235.29999, 239.29999], ..., [295.9 , 296.19998, ..., 295.9 , 295.19998], [296.29 , 296.79 , ..., 296.79 , 296.6 ]], [[242.09999, 242.7 , ..., 233.59999, 235.79999], [243.59999, 244.09999, ..., 232.5 , 235.7 ], ..., [296.19998, 296.69998, ..., 295.5 , 295.1 ], [296.29 , 297.19998, ..., 296.4 , 296.6 ]], ..., [[244.79999, 244.39 , ..., 242.7 , 244.79999], [246.7 , 247.09999, ..., 237.79999, 240.2 ], ..., [297.79 , 297.19998, ..., 296.4 , 295.29 ], [297.9 , 297.69998, ..., 297.19998, 297. ]], [[243.89 , 243.79999, ..., 240.29999, 242.59999], [245.5 , 245.79999, ..., 236.59999, 239. ], ..., [297.6 , 297. , ..., 295.6 , 295. ], [298.1 , 297.69998, ..., 296.79 , 297.1 ]]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2013-01-03T06:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Sie können die Originaldaten wiederherstellen, indem Sie eine Verbindung in Richtung "Zeit" herstellen.
xr.concat([da0, da1], dim='time')
<xarray.DataArray 'air' (time: 2920, lat: 25, lon: 53)> array([[[241.2 , 242.5 , 243.5 , ..., 232.79999, 235.5 , 238.59999], [243.79999, 244.5 , 244.7 , ..., 232.79999, 235.29999, 239.29999], [250. , 249.79999, 248.89 , ..., 233.2 , 236.39 , 241.7 ], ..., [296.6 , 296.19998, 296.4 , ..., 295.4 , 295.1 , 294.69998], [295.9 , 296.19998, 296.79 , ..., 295.9 , 295.9 , 295.19998], [296.29 , 296.79 , 297.1 , ..., 296.9 , 296.79 , 296.6 ]], [[242.09999, 242.7 , 243.09999, ..., 232. , 233.59999, 235.79999], [243.59999, 244.09999, 244.2 , ..., 231. , 232.5 , 235.7 ], [253.2 , 252.89 , 252.09999, ..., 230.79999, 233.39 , 238.5 ], ... [293.69 , 293.88998, 295.38998, ..., 295.09 , 294.69 , 294.29 ], [296.29 , 297.19 , 297.59 , ..., 295.29 , 295.09 , 294.38998], [297.79 , 298.38998, 298.49 , ..., 295.69 , 295.49 , 295.19 ]], [[245.09 , 244.29 , 243.29 , ..., 241.68999, 241.48999, 241.79 ], [249.89 , 249.29 , 248.39 , ..., 239.59 , 240.29 , 241.68999], [262.99 , 262.19 , 261.38998, ..., 239.89 , 242.59 , 246.29 ], ..., [293.79 , 293.69 , 295.09 , ..., 295.29 , 295.09 , 294.69 ], [296.09 , 296.88998, 297.19 , ..., 295.69 , 295.69 , 295.19 ], [297.69 , 298.09 , 298.09 , ..., 296.49 , 296.19 , 295.69 ]]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Beachten Sie auch, dass die Zeitachse ebenfalls wiederhergestellt wurde.
Angenommen, Sie haben zwei DataArrays wie folgt:
da0 = da.isel(time=0)
da1 = da.isel(time=1)
da0
<xarray.DataArray 'air' (lat: 25, lon: 53)> array([[241.2 , 242.5 , 243.5 , ..., 232.79999, 235.5 , 238.59999], [243.79999, 244.5 , 244.7 , ..., 232.79999, 235.29999, 239.29999], [250. , 249.79999, 248.89 , ..., 233.2 , 236.39 , 241.7 ], ..., [296.6 , 296.19998, 296.4 , ..., 295.4 , 295.1 , 294.69998], [295.9 , 296.19998, 296.79 , ..., 295.9 , 295.9 , 295.19998], [296.29 , 296.79 , 297.1 , ..., 296.9 , 296.79 , 296.6 ]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 time datetime64[ns] 2013-01-01 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
So kombinieren Sie dies in Richtung der Zeitachse:
xr.concat([da0, da1], dim='time')
<xarray.DataArray 'air' (time: 2, lat: 25, lon: 53)> array([[[241.2 , 242.5 , 243.5 , ..., 232.79999, 235.5 , 238.59999], [243.79999, 244.5 , 244.7 , ..., 232.79999, 235.29999, 239.29999], [250. , 249.79999, 248.89 , ..., 233.2 , 236.39 , 241.7 ], ..., [296.6 , 296.19998, 296.4 , ..., 295.4 , 295.1 , 294.69998], [295.9 , 296.19998, 296.79 , ..., 295.9 , 295.9 , 295.19998], [296.29 , 296.79 , 297.1 , ..., 296.9 , 296.79 , 296.6 ]], [[242.09999, 242.7 , 243.09999, ..., 232. , 233.59999, 235.79999], [243.59999, 244.09999, 244.2 , ..., 231. , 232.5 , 235.7 ], [253.2 , 252.89 , 252.09999, ..., 230.79999, 233.39 , 238.5 ], ..., [296.4 , 295.9 , 296.19998, ..., 295.4 , 295.1 , 294.79 ], [296.19998, 296.69998, 296.79 , ..., 295.6 , 295.5 , 295.1 ], [296.29 , 297.19998, 297.4 , ..., 296.4 , 296.4 , 296.6 ]]], dtype=float32) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 2013-01-01T06:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Auf diese Weise verbinden Sie eine Skalarkoordinate mit der Bezeichnung "Zeit" in "da0", "da1", in diese Richtung. Sie können die Zeitachse zu einer neuen Dimensionskoordinate machen (indem Sie im Schlüsselwort "dim" einen Namen angeben, z. B. "dim =" time ").
Alternativ können Sie eine neue Koordinatenachse für diesen Namen erstellen, indem Sie dem Schlüsselwort "dim" ein DataArray geben.
Ein weiterer Vorteil von xarray besteht darin, dass Daten wie DataArray und Dataset konsistent und in sich geschlossen gespeichert werden können. Es unterstützt mehrere Dateiformate, aber die am einfachsten zu verwendende ist wahrscheinlich netCDF.
Wikipedia hat auch eine Erklärung.
NetCDF ist ein modellunabhängiges Binärformat des Computers (modellunabhängig), kann Daten als Array lesen und schreiben (Array-orientiert) und kann zusätzlich zu den Daten Erklärungen zu den Daten speichern (selbstbeschreibend). ). NetCDF ist ein internationaler Standard im Open Geospatial Consortium, einem internationalen Konsortium, das offene geografische Informationsstandards entwickelt.
Derzeit werden die Versionen 3 und 4 gewartet, es ist jedoch sicherer, Version 4 zu verwenden. Version 4 entspricht dem HDF5-Standard, sodass auch ein normaler HDF5-Leser den Inhalt lesen kann.
Die offizielle Erweiterung lautet ".nc".
Das Paket "netcdf4" ist erforderlich, um im netCDF-Format zu speichern.
pip install netcdf4
Oder
conda install netcdf4
Lassen Sie es uns ausführen und auf Ihrem System installieren.
Führen Sie die Methode .to_netcdf
aus, um das xarray-Objekt im netCDF-Format zu speichern.
data.to_netcdf('test.nc')
/home/keisukefujii/miniconda3/envs/xarray/lib/python3.7/site-packages/ipykernel_launcher.py:1: SerializationWarning: saving variable air with floating point data as an integer dtype without any _FillValue to use for NaNs
"""Entry point for launching an IPython kernel.
Sie sollten jetzt test.nc
in Ihrem aktuellen Pfad gespeichert haben.
Um die gespeicherte Datei zu laden, führen Sie "xr.load_dataset" aus.
xr.load_dataset('test.nc')
<xarray.Dataset> Dimensions: (lat: 25, lon: 53, time: 2920) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 ... 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 ... 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Data variables: air (time, lat, lon) float32 241.2 242.5 ... 296.19 295.69 mean_temperature (lat, lon) float32 260.37564 260.1826 ... 297.30502 Attributes: Conventions: COARDS title: 4x daily NMC reanalysis (1948) description: Data is from NMC initialized reanalysis\n(4x/day). These a... platform: Model references: http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...
Wie Sie sehen können, werden nicht nur der Teil des Arrays, sondern auch der Achsname, die Koordinatenwerte und andere Informationen in "Attributen" gespeichert.
scipy.io.netcdf
Das xarray .to_netcdf
verwendet standardmäßig die Bibliothek netcdf4
, verwendet jedoch scipy.io.netcdf
, wenn es nicht auf Ihrem System installiert ist. Scipy.io.netcdf
unterstützt jedoch Version 3, die mit Version 4 nicht kompatibel ist und verwirrend sein kann.
Vergessen Sie nicht, "netcdf4" auf Ihrem System zu installieren. Alternativ können Sie das zu verwendende Paket explizit angeben, z. B. ".to_netcdf (" test.nc ", engine =" netcdf4 ")".
Dateien im NetCDF-Format können zufällig gelesen werden. Wenn Sie daher nur die Daten eines bestimmten Teils der Datei verwenden möchten, ist es daher effizient, alle Daten bei Bedarf zu lesen, anstatt sie zuerst von der Festplatte zu lesen. Insbesondere bei Dateien, die zu groß sind, um im Speicher gespeichert zu werden, ist eine solche Verarbeitung unerlässlich. Dies wird als Out-of-Memory-Verarbeitung bezeichnet.
Die Verarbeitung von Speichermangel in xarray wird gestern als ziemlich wichtig eingestuft, und verschiedene Implementierungen sind im Gange. Ich werde die Details in einem anderen Artikel vorstellen und hier nur die grundlegendsten Inhalte erwähnen.
Die Verarbeitung zu wenig Speicher wird ausgeführt, indem beim Laden "open_dataset" anstelle von "load_dataset" ausgeführt wird.
unloaded_data = xr.open_dataset('test.nc')
unloaded_data
<xarray.Dataset> Dimensions: (lat: 25, lon: 53, time: 2920) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 ... 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 ... 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Data variables: air (time, lat, lon) float32 ... mean_temperature (lat, lon) float32 ... Attributes: Conventions: COARDS title: 4x daily NMC reanalysis (1948) description: Data is from NMC initialized reanalysis\n(4x/day). These a... platform: Model references: http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...
Wenn Sie sich zum Beispiel "Datenvariablen" ansehen, können Sie sehen, dass in "Luft" keine Nummer ist, sondern nur "...".
Dies zeigt an, dass keine Daten gelesen wurden. Da jedoch die Koordinatenachsen immer gelesen werden, kann die obige Indizierungsarbeit so ausgeführt werden, wie sie ist.
unloaded_data['air'].sel(lat=60, method='nearest')
<xarray.DataArray 'air' (time: 2920, lon: 53)> [154760 values with dtype=float32] Coordinates: lat float32 60.0 * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Attributes: long_name: 4xDaily Air temperature at sigma level 995 units: degK precision: 2 GRIB_id: 11 GRIB_name: TMP var_desc: Air temperature dataset: NMC Reanalysis level_desc: Surface statistic: Individual Obs parent_stat: Other actual_range: [185.16 322.1 ]
Wenn ich eine Variable auswähle oder indiziere, wird sie immer noch nicht geladen. Es wird zum ersten Mal in den Speicher geladen, wenn es berechnet wird oder wenn ".data" oder ".values" aufgerufen wird.
Sie können auch die Methode .compute ()
verwenden, um sie explizit zu laden.
unloaded_data.compute()
<xarray.Dataset> Dimensions: (lat: 25, lon: 53, time: 2920) Coordinates: * lat (lat) float32 75.0 72.5 70.0 67.5 ... 22.5 20.0 17.5 15.0 * lon (lon) float32 200.0 202.5 205.0 ... 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00 Data variables: air (time, lat, lon) float32 241.2 242.5 ... 296.19 295.69 mean_temperature (lat, lon) float32 260.37564 260.1826 ... 297.30502 Attributes: Conventions: COARDS title: 4x daily NMC reanalysis (1948) description: Data is from NMC initialized reanalysis\n(4x/day). These a... platform: Model references: http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...
open_dataset
, open_dataarray
sperrt die Datei für das zukünftige Lesen. Wenn Sie eine Datei mit demselben Namen in einem anderen Programm berühren, tritt daher ein Fehler auf.
Betrachten Sie beispielsweise den Fall, in dem das Ergebnis einer zeitaufwändigen Berechnung jedes Mal als ".nc" -Datei ausgegeben wird. Wenn Sie den Fortschritt sehen und mit "open_dataset" öffnen möchten, schlagen alle nachfolgenden Versuche, in diese Datei zu schreiben, fehl. Es ist besser, wenn es nur fehlschlägt und stoppt, aber es scheint, dass es häufig vorhandene Daten zerstört. Dieser Prozess mit nicht genügend Arbeitsspeicher sollte mit Vorsicht angewendet werden.
Mit der Anweisung "with" können Sie sicherstellen, dass die Datei geschlossen und entsperrt wird, wie unten gezeigt.
with xr.open_dataset('test.nc') as f:
print(f)
<xarray.Dataset>
Dimensions: (lat: 25, lon: 53, time: 2920)
Coordinates:
* lat (lat) float32 75.0 72.5 70.0 67.5 ... 22.5 20.0 17.5 15.0
* lon (lon) float32 200.0 202.5 205.0 ... 325.0 327.5 330.0
* time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00
Data variables:
air (time, lat, lon) float32 ...
mean_temperature (lat, lon) float32 ...
Attributes:
Conventions: COARDS
title: 4x daily NMC reanalysis (1948)
description: Data is from NMC initialized reanalysis\n(4x/day). These a...
platform: Model
references: http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...
Wie oben erwähnt, können Sie die Daten mit xarray reibungslos analysieren, wenn Sie die Daten im netcdf-Format speichern. Wenn Sie Daten für Experimente oder Simulationen erstellen, empfiehlt es sich, eine Datenstruktur zu erstellen, die die nachfolgende Analyse berücksichtigt, und diese im netcdf-Format einschließlich dieser zu speichern.
Es wird empfohlen, die folgenden Daten unterdrückt zu halten.
Im Falle eines Experiments denke ich, dass es mit der folgenden Struktur gespeichert werden sollte.
from datetime import datetime
#Nehmen wir an, dass dies Bilddaten sind, die mit einer Kamera aufgenommen wurden.
raw_data = np.arange(512 * 2048).reshape(512, 2048)
#Die x- und y-Achsenkoordinaten des Bildes.
x = np.arange(512)
y = np.arange(2048)
#Positionsdaten für jedes Pixel des Bildes
r = 300.0
X = r * np.cos(x / 512)[:, np.newaxis] + r * np.sin(y / 2048)
Y = r * np.sin(x / 512)[:, np.newaxis] - r * np.cos(y / 2048)
#Im Experiment verwendete Parameter
p0 = 3.0
p1 = 'normal'
#Experimentierzeit
now = datetime.now()
data = xr.DataArray(
raw_data, dims=['x', 'y'],
coords={'x': x, 'y': y,
'X': (('x', 'y'), X),
'Y': (('x', 'y'), Y),
'p0': p0, 'p1': p1,
'datetime': now},
attrs={'camera type': 'flash 4',
'about': 'Example of the recommended data structure.'})
data
<xarray.DataArray (x: 512, y: 2048)> array([[ 0, 1, 2, ..., 2045, 2046, 2047], [ 2048, 2049, 2050, ..., 4093, 4094, 4095], [ 4096, 4097, 4098, ..., 6141, 6142, 6143], ..., [1042432, 1042433, 1042434, ..., 1044477, 1044478, 1044479], [1044480, 1044481, 1044482, ..., 1046525, 1046526, 1046527], [1046528, 1046529, 1046530, ..., 1048573, 1048574, 1048575]]) Coordinates: * x (x) int64 0 1 2 3 4 5 6 7 8 ... 504 505 506 507 508 509 510 511 * y (y) int64 0 1 2 3 4 5 6 7 ... 2041 2042 2043 2044 2045 2046 2047 X (x, y) float64 300.0 300.1 300.3 300.4 ... 414.7 414.8 414.9 414.9 Y (x, y) float64 -300.0 -300.0 -300.0 -300.0 ... 89.66 89.79 89.91 p0 float64 3.0 p1 <U6 'normal' datetime datetime64[ns] 2020-11-13T03:31:56.219372 Attributes: camera type: flash 4 about: Example of the recommended data structure.
Durch das Sammeln von Dingen, die sich während des Experiments ändern können, in Skalarkoordinaten ist es später einfacher zu analysieren, wenn Sie die Abhängigkeiten von ihnen kennen möchten.
Reduction .sum
, .mean
, etc
Reduktionsprozesse wie "np.sum" und "np.mean" werden als Methoden bereitgestellt.
Mit np.sum
können Sie beispielsweise angeben, in welche Achsenrichtung hinzugefügt werden soll. In ähnlicher Weise können Sie mit xarray eine Achse als Achsnamen angeben.
data = xr.tutorial.open_dataset('air_temperature')['air']
data.sum('lat')
<xarray.DataArray 'air' (time: 2920, lon: 53)> array([[6984.9497, 6991.6606, 6991.5303, ..., 6998.77 , 7007.8804, 7016.5605], [6976.4307, 6988.45 , 6993.2407, ..., 6994.3906, 7006.7505, 7019.941 ], [6975.2603, 6982.02 , 6988.77 , ..., 6992.0503, 7004.9404, 7020.3506], ..., [6990.7505, 6998.3496, 7013.3496, ..., 6995.05 , 7008.6504, 7019.4497], [6984.95 , 6991.6504, 7007.949 , ..., 6994.15 , 7008.55 , 7020.8506], [6981.75 , 6983.85 , 6997.0503, ..., 6985.6494, 6999.2495, 7012.0493]], dtype=float32) Coordinates: * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0 * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00
Wenn Sie auf diese Weise in einer bestimmten axialen Richtung addieren, gibt es in dieser Richtung keine Koordinatenachsen. Die anderen Achsen bleiben erhalten.
Bei der Ausführung von ".sum" usw. wird "np.nansum" standardmäßig anstelle von "np.sum" aufgerufen, und das Überspringen der Berechnung "Nan" wird durchgeführt. Wenn Sie "Nan" nicht überspringen möchten (wenn Sie "np.sum" anstelle von "np.nansum" verwenden möchten), müssen Sie "skipna = False" angeben.
.plot
DataArray
verfügt über eine Plot
-Methode, mit der sich der Inhalt der Daten leicht visualisieren lässt.
data.sel(time='2014-08-30 08:00', method='nearest').plot()
<matplotlib.collections.QuadMesh at 0x7f9a98557310>
Es ist vielleicht besser, es als einfach zu betrachten, als ein endgültiges Diagramm des Papiers / Berichts zu erstellen, aber um die Daten mit Jupyter, Ipython usw. zu visualisieren und zu verstehen und mit der Analyse fortzufahren. Sehr bequem zu bedienen.
Recommended Posts