Wir haben eine Erweiterung veröffentlicht, mit der Sie Xarray-Daten wie eine Python-Datenklasse definieren können.

TL;DR

xarray ist ein Python-Paket, das in der Datenanalyse wie NumPy und pandas als Werkzeug zum Verarbeiten von Daten mit Metadaten (Achsenbeschriftungen usw.) verwendet wird, die an ein mehrdimensionales Array, aber verschiedene Daten angehängt sind Während ich mich mit xarray (DataArray) beschäftige, fühle ich mich immer mehr wie folgt.

Es gibt viele Möglichkeiten, dies zu erreichen, aber sind die Datenklassen ([Datenklassen]), die in der Standardbibliothek von Python 3.7 enthalten sind, dasselbe Problem? Mir ist aufgefallen, dass ich es mit einem einfachen Schreibstil gelöst habe. Aus diesem Grund haben wir ein Paket "xarray-custom" veröffentlicht, mit dem eine benutzerdefinierte DataArray-Klasse auf dieselbe Weise wie eine Datenklasse erstellt werden kann (Sie können sie mit pip installieren).

from xarray_custom import ctype, dataarrayclass

@dataarrayclass(accessor='img')
class Image:
    """DataArray class to represent images."""

    dims = 'x', 'y'
    dtype = float
    x: ctype('x', int) = 0
    y: ctype('y', int) = 0

    def normalize(self):
        return self / self.max()

Im Folgenden werde ich erklären, wie dieser Code funktioniert, und dabei die Datenklassen und DataArary von Python ansprechen.

Python's dataclass

Erstens ist die Python-Datenklasse eine Funktion (Class Decorator), mit der benutzerdefinierte Datenstrukturen einfach erstellt werden können.

from dataclasses import dataclass

@dataclass
class Coordinates:
    x: float
    y: float

    @classmethod
    def origin(cls):
        return cls(0.0, 0.0)

    def norm(self):
        return (self.x ** 2 + self.y **2) ** 0.5

Wenn Sie eine Klasse wie diese definieren,

coord = Coordinates(x=3, y=4)

Es wird eine Klasse erstellt, in der Daten wie (Ursprünglich müssen verschiedene spezielle Methoden wie "init ()" implementiert werden). Ich denke, das Folgende sind mögliche Vorteile der Definition einer Datenklasse auf diese Weise.

xarray's DataArray

Schauen wir uns als nächstes die Datenstruktur von xarray an. DataArray verwendet eine Datenstruktur, die aus NumPy mehrdimensionalem Array (Daten), Achsen (Dimensionen; eine Art von Metadaten) und Metadaten (Koordinaten) besteht. Das folgende Beispiel soll Daten in einem DataArray eines monochromatischen Bildes darstellen, das aus zwei xy-Achsen besteht.

from xarray import DataArray

image = DataArray(data=[[0, 1], [2, 3]], dims=('x', 'y'),
                  coords={'x': [0, 1], 'y': [0, 1]})
print(image)

# <xarray.DataArray (x: 2, y: 2)>
# array([[0., 1.],
#        [2., 3.]])
# Coordinates:
#   * x        (x) int64 0 1
#   * y        (y) int64 0 1

Da "DataArray" eine Klasse ist, besteht eine übliche Methode zum Definieren eines benutzerdefinierten DataArray darin, eine neue Klasse mit "DataArray" als Unterklasse zu erstellen. Wenn Sie die Definition jedoch fest in "__init __ ()" usw. codieren, besteht das Problem, dass sie nicht wiederverwendet werden kann. Darüber hinaus empfehlen xarray und pandas zunächst nicht aktiv die Unterklasse, und es ist besser, eine benutzerdefinierte Verarbeitung usw. über ein spezielles Objekt namens Accessor zu implementieren.

One standard solution to this problem is to subclass Dataset and/or DataArray to add domain specific functionality. However, inheritance is not very robust. It’s easy to inadvertently use internal APIs when subclassing, which means that your code may break when xarray upgrades. Furthermore, many builtin methods will only return native xarray objects. (Extending xarray - xarray 0.15.0 documentation)

xarray's dataarrayclass

Es ist endlich das Hauptthema. Um die eingangs erwähnte Anfrage unter Berücksichtigung der Umstände von xarray (DataArray) zu realisieren,

Mir wurde klar, dass ich etwas brauchte. Daher habe ich mich in xarray-custom entschlossen, mich an die Python-Datenklasse zu gewöhnen und sie zu implementieren, indem ich ** die benutzerdefinierte DataArray-Klasse mit einem Klassendekorator (dataarrayclass) ** dynamisch modifiziere **. Mit xarray-custom kann das obige monochromatische Bildbeispiel wie folgt definiert werden.

from xarray_custom import ctype, dataarrayclass

@dataarrayclass(accessor='img')
class Image:
    """DataArray class to represent images."""

    dims = 'x', 'y'
    dtype = float
    x: ctype('x', int) = 0
    y: ctype('y', int) = 0

    def normalize(self):
        return self / self.max()

Wenn Sie die Datenklasse kennen, können Sie hoffentlich irgendwie verstehen, was dieser Code ohne Erklärung tut. Die Punkte hier sind die folgenden drei Punkte.

Hier ist ctype eine Funktion zum Generieren eines speziellen Typs (einer Klasse), der Metadaten definiert. Lassen Sie uns nun tatsächlich ein benutzerdefiniertes Array generieren.

image = Image([[0, 1], [2, 3]], x=[0, 1], y=[0, 1])
print(image)

# <xarray.DataArray (x: 2, y: 2)>
# array([[0., 1.],
#        [2., 3.]])
# Coordinates:
#   * x        (x) int64 0 1
#   * y        (y) int64 0 1

Sie können sehen, dass die Achsen und Metadaten vordefiniert sind, sodass das Schreiben viel einfacher ist als im obigen DataArray-Beispiel. Es unterscheidet sich von der Datenklasse darin, dass die Typinformationen tatsächlich verwendet werden, um den Typ des Arrays zu bestimmen. Im obigen Beispiel wird die Liste der Ganzzahlen so eingegeben, dass sie im DataArray schweben. Wenn eine (implizite) Typkonvertierung nicht möglich ist, wird "ValueError" ausgelöst. Sie können auch keinen Typ angeben (in diesem Fall werden Objekte eines beliebigen Typs akzeptiert).

Instance methods via an accessor

Gemäß der xarray -Richtlinie kann die in der Klasse definierte Instanzmethode (im obigen Beispiel "normalize ()") über den Accessor ausgeführt werden. Wenn Sie ohne Accessor ausgeführt werden, wird ein AttributeError ausgelöst.

normalized = image.img.normalize()
print(normalized)

# <xarray.DataArray (x: 2, y: 2)>
# array([[0.        , 0.33333333],
#        [0.66666667, 1.        ]])
# Coordinates:
#   * x        (x) int64 0 1
#   * y        (y) int64 0 1

Special functions as class methods

Als spezielle Array-Generierung werden automatisch "Nullen ()" - "Einsen ()" - "leer ()" - "voll ()", die mit NumPy vertraut sind, automatisch als Klassenmethoden hinzugefügt. zeros_like () usw. sind in der Top-Level-Funktion von xarray definiert, also lasst uns das verwenden.

uniform = Image.ones((2, 3))
print(uniform)

# <xarray.DataArray (x: 2, y: 3)>
# array([[1., 1., 1.],
#        [1., 1., 1.]])
# Coordinates:
#   * x        (x) int64 0 0
#   * y        (y) int64 0 0 0

Misc

Ist die "Dataarray-Klasse" bisher doch auch nicht die "DataArray" -Klasse? Einige Leute haben vielleicht gedacht. Das resultierende DataArray ist jedoch tatsächlich eine echte "DataArray" -Instanz. Umgekehrt handelt es sich im obigen Beispiel nicht um eine "Image" -Instanz.

print(type(image)) # xarray.core.dataarray.DataArray

Dies liegt daran, dass die "dataarray-Klasse" intern "new __ ()" anstelle von " init __ ()" generiert und "__new __ ()" ein DataArray zurückgibt. Daher sollte beachtet werden, dass auf Klassenvariablen usw. nicht wie auf eine aus einer normalen Klasse erstellte Instanz zugegriffen werden kann.

Ich habe den Eindruck, dass xarray weniger Artikel enthält und weniger bekannt ist als NumPy und pandas, aber es ist definitiv nützlich für Aufgaben, die sich mit mehrdimensionalen Arrays befassen, daher würde ich es gerne mehr und mehr verwenden. xarray-custom hat in den frühen Entwicklungsstadien nur wenige Funktionen, aber ich hoffe, durch die Entwicklung und die Artikel dieser Erweiterungen so viel wie möglich zur Community beizutragen.

References

Recommended Posts

Wir haben eine Erweiterung veröffentlicht, mit der Sie Xarray-Daten wie eine Python-Datenklasse definieren können.
Erstellt einen Dienst, mit dem Sie J-League-Daten durchsuchen können
Ein Hinweis, mit dem Sie die Python-Umgebung von Pineapple mit pyenv ändern können
Wir haben ein Python-Modul veröffentlicht, das ein regionales Netz für Japan generiert
Einführung von "Scikit-Mobility", einer Bibliothek, mit der Sie menschliche Flussdaten mit Python einfach analysieren können (Teil 1)
Erstellen Sie ein Plugin, mit dem Sie in Python nach Registerkarten für Sublime Text 3 suchen können
Lern-Roadmap, mit der Sie Services mit Python von Grund auf neu entwickeln und veröffentlichen können
Python-Skript, das den Status des Servers über den Browser überprüfen kann
So importieren Sie Dateien in Python an eine beliebige Stelle
Ein Python-Skript, das Oracle-Datenbankdaten in CSV konvertiert
[Road to Intermediate Python] Rufen Sie eine Klasseninstanz wie eine Funktion mit __call__ auf
Python-Muster, die für die Welt freigegeben und später überprüft wurden
[Python] Ich habe einen Dekorateur gemacht, der keinen Nutzen zu haben scheint.
[Python3] Code, der verwendet werden kann, wenn Sie ein Bild in einer bestimmten Größe ausschneiden möchten
Wir haben LINE BOT veröffentlicht, mit dem Sie anhand von Standortinformationen nach Hotels und Bars suchen können.
[Python3] Code, der verwendet werden kann, wenn Sie die Erweiterung eines Bildes sofort ändern möchten
[Python] Wie man eine Klasse iterierbar macht
Ich habe versucht, eine Klasse zu erstellen, mit der Json in Python problemlos serialisiert werden kann
Was gefällt Ihnen an der Konvertierung eines Arrays (einer Liste) in einen String?
Ich musste im Unterricht keinen Dekorateur schreiben. Danke Kontextmanager
Einführung in das Buch "Erstellen einer profitablen KI mit Python", mit dem Sie in kürzester Zeit maschinelles Lernen erlernen können
Ein Memo zum Generieren dynamischer Klassenvariablen aus Wörterbuchdaten (dict), die in Python3 nur Standardtypdaten enthalten