TL;DR
xarray est un package Python utilisé dans l'analyse de données comme NumPy et pandas comme outil de gestion de données avec des métadonnées (étiquettes d'axes, etc.) attachées à un tableau multidimensionnel, mais diverses données Comme je m'occupe de xarray (DataArray), je me sens de plus en plus comme suit.
--Je veux une fonction de génération de tableau qui spécifie les axes (dimensions) et le type (dtype) d'un tableau multidimensionnel.
Il existe de nombreuses façons d'y parvenir, mais les classes de données (dataclasses) qui sont apparues dans la bibliothèque standard de Python 3.7 posent-elles le même problème? J'ai remarqué que je l'ai résolu avec un style d'écriture simple. Par conséquent, nous avons publié un package "xarray-custom" pour créer une classe DataArray définie par l'utilisateur de la même manière qu'une classe de données, je vais donc l'introduire (vous pouvez l'installer avec pip).
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()
Ci-dessous, je vais expliquer comment ce code fonctionne, en abordant les classes de données de Python et DataArary.
Python's dataclass
Tout d'abord, la classe de données Python est une fonction (décorateur de classe) qui facilite la création de structures de données définies par l'utilisateur.
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
Si vous définissez une classe comme celle-ci,
coord = Coordinates(x=3, y=4)
Il crée une classe qui stocke des données comme (À l'origine, il est nécessaire d'implémenter diverses méthodes spéciales telles que __init __ ()
). Je pense que les avantages suivants sont possibles à définir une classe de données de cette manière.
norm ()
dans l'exemple ci-dessus) peut être réalisé avec une méthode d'instance.xarray's DataArray
Ensuite, regardons la structure de données de xarray. DataArray prend une structure de données composée d'un tableau multidimensionnel NumPy, d'axes (dimensions; un type de métadonnées) et de métadonnées (coordonnées). L'exemple suivant vise à représenter les données dans un DataArray d'une image monochromatique constituée de deux axes de xy.
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
Puisque DataArray
est une classe, une manière courante de définir un DataArray défini par l'utilisateur est de créer une nouvelle classe avec DataArray
comme sous-classe. Cependant, si vous codez en dur la définition en __init __ ()
etc., il y a un problème qui ne peut pas être réutilisé. De plus, xarray et pandas ne recommandent pas activement de sous-classer en premier lieu, et il est préférable d'implémenter le traitement défini par l'utilisateur, etc. via un objet spécial appelé accesseur.
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
C'est finalement le sujet principal. Afin de réaliser la requête mentionnée au début, compte tenu des circonstances de xarray (DataArray),
-Fournit un moyen de générer un tableau sans coder en dur la définition des (méta) données
J'ai réalisé que j'avais besoin de quelque chose. Par conséquent, dans xarray-custom, j'ai décidé de m'habituer à la classe de données Python et de l'implémenter en ** modifiant dynamiquement la classe DataArray définie par l'utilisateur avec un décorateur de classe (dataarrayclass) **. En utilisant xarray-custom, l'exemple d'image monochromatique ci-dessus peut être défini comme suit.
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()
En connaissant la classe de données, j'espère que vous pourriez comprendre ce que fait ce code sans explication. Les points ici sont les trois points suivants.
--Spécifiez l'axe des données (`` x ',' y') et tapez (
float`) avec des variables de classe
Ici, ctype
est une fonction pour générer un type spécial (classe) qui définit les métadonnées. Générons maintenant un tableau défini par l'utilisateur.
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
Vous pouvez voir que les axes et les métadonnées sont prédéfinis, il est donc beaucoup plus simple à écrire que l'exemple DataArray ci-dessus. Elle diffère de la classe de données en ce que les informations de type sont en fait utilisées pour déterminer le type du tableau. Dans l'exemple ci-dessus, la liste d'entiers est tapée pour flotter dans le DataArray. Si la conversion de type (implicite) n'est pas possible, ValueError
est renvoyé. Vous pouvez également ne spécifier aucun type (auquel cas, les objets de tout type seront acceptés).
Instance methods via an accessor
Selon la politique xarray, la méthode d'instance définie dans la classe (normalize ()
dans l'exemple ci-dessus) peut être exécutée via l'accesseur. L'exécution sans accesseur lèvera ʻAttribute Error`.
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
En tant que génération de séquence spéciale, zeros ()
・ ʻones () ・ ʻempty ()
・ full ()
, qui est familier avec NumPy, est automatiquement ajouté comme méthode de classe. zeros_like ()
etc. sont définis dans la fonction de niveau supérieur de xarray, alors utilisons-le.
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
Jusqu'à présent, la classe dataarray
ne sous-classe-t-elle pas également DataArray
après tout? Certaines personnes ont peut-être pensé. Cependant, le DataArray résultant est en fait une véritable instance de DataArray
. Inversement, dans l'exemple ci-dessus, ce n'est pas une instance ʻImage`.
print(type(image)) # xarray.core.dataarray.DataArray
C'est parce que la classe dataarray
génère en interne __new __ () ʻau lieu de
__ init __ (), et
__new __ () `retourne un DataArray. Par conséquent, il convient de noter que les variables de classe, etc. ne sont pas accessibles comme une instance créée à partir d'une classe ordinaire.
J'ai l'impression que xarray a moins d'articles et est moins connu que NumPy et pandas, mais il est certainement utile pour les tâches traitant des tableaux multidimensionnels, alors j'aimerais l'utiliser de plus en plus. xarray-custom a peu de fonctions dans les premiers stades de développement, mais j'espère contribuer autant que possible à la communauté à travers le développement et les articles de ces extensions.
References
Recommended Posts