Créer des tableaux espacés uniformément ou non – Python réel

By | novembre 30, 2020

Formation gratuite Python

Vous avez vu comment créer et utiliser une plage de nombres régulièrement espacée. Cependant, il peut arriver que vous ayez besoin d’un tableau qui n’est pas espacé linéairement. Les étapes entre chaque valeur peuvent devoir être logarithmiques ou suivre un autre modèle. Dans cette dernière section, vous découvrirez quelles sont vos options pour créer ce type de tableau.

Espaces logarithmiques

La fonction np.logspace () crée un espace logarithmique dans lequel les nombres créés sont régulièrement espacés sur une échelle logarithmique.

Une fois que vous maîtrisez np.linspace (), vous serez bien équipé pour utiliser np.logspace () puisque les paramètres d'entrée et la sortie renvoyée des deux fonctions sont très similaires. Un paramètre qui manque dans np.logspace () est repasser car il n'y a pas une seule valeur pour représenter le changement de pas entre les nombres successifs.

np.logspace () a un paramètre d'entrée supplémentaire, base, avec une valeur par défaut de dix. Une autre différence clé est que début et Arrêtez représentent les points de début et de fin logarithmiques. La première valeur du tableau est basedébut, et la valeur finale est baseArrêtez:

>>>

>>> importer engourdi comme np
>>> np.espace journal(0, 4, 5)
tableau ([1.e+00, 1.e+01, 1.e+02, 1.e+03, 1.e+04])

Cela crée un espace logarithmique avec 5 éléments allant de dix0 à dix4, ou de 1 à 10 000. Le tableau de sortie affiche les nombres 1, dix, 100, 1000, et 10 000 en notation scientifique. Bien que la base 10 soit la valeur par défaut, vous pouvez créer des espaces logarithmiques avec n'importe quelle base:

>>>

>>> np.espace journal(1, dix, 20, base=np.e)
tableau ([271828183e+00436528819e+00701021535e+00112577033e+01[271828183e+00436528819e+00701021535e+00112577033e+01[271828183e+00436528819e+00701021535e+00112577033e+01[271828183e+00436528819e+00701021535e+00112577033e+01
                            1.80787433e + 01, 2.90326498e + 01, 4.66235260e + 01, 7.48727102e + 01,
                            1.20238069e + 02, 1.93090288e + 02, 3.10083652e + 02, 4.97963268e + 02,
                            7.99679103e + 02, 1.28420450e + 03, 2.06230372e + 03, 3.31185309e + 03,
                            5.31850415e + 03, 8.54098465e + 03, 1.37159654e + 04, 2.20264658e + 04])

Cet exemple montre un espace logarithmique en base e. Dans la section suivante, vous verrez comment créer d’autres plages non linéaires qui ne sont pas logarithmiques.

Autres plages non linéaires

Vous pouvez maintenant créer des espaces linéaires et logarithmiques. Vous pouvez également avoir besoin d'une plage de nombres qui suivent d'autres intervalles non linéaires. Vous pouvez y parvenir en transformer un espace linéaire.

Commencez par créer un espace linéaire:

>>>

>>> importer engourdi comme np
>>> X_ = np.linspace(1, dix, dix)
>>> X_
tableau ([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.])

Vous pouvez maintenant transformer cela en une plage de nombres linéaires sur X2:

>>>

>>> X_ = X_ ** 2
>>> X_
tableau ([  1.,   4.,   9.,  16.,  25.,  36.,  49.,  64.,  81., 100.])

Cela peut sembler familier. Il s’agit de la même méthode que vous avez utilisée pour représenter les fonctions mathématiques précédemment dans ce didacticiel. En effet, c'est exactement le même. La raison pour laquelle vous voudrez peut-être parfois penser à cela comme la création d'un tableau espacé de manière non uniforme deviendra plus claire dans la section suivante, lorsque vous examinerez un exemple concret.

Exemple: simulation d'une planète en orbite

Dans cette section, vous allez créer une simulation d’une planète en orbite autour de son soleil. Pour simplifier légèrement la simulation, vous pouvez supposer que l’orbite de la planète est circulaire plutôt qu’elliptique.

L'équation qui décrit un cercle est une fonction de X et y et dépend du rayon R:

Équation d'un cercle

Donc si le X-positions de la planète sont définies, les y-positions seront données en réorganisant l'équation ci-dessus:

Équation d'un cercle en termes de y

La planète peut donc être placée à un ensemble de coordonnées (X, y), et aussi longtemps que y est donnée par l'équation ci-dessus, la planète restera en orbite. Son emplacement sera sur la circonférence d'un cercle.

Vous connaissez maintenant bien np.linspace (), donc la première tentative peut utiliser les méthodes que vous connaissez déjà:

importer engourdi comme np

échantillonnage = 50
R = 50

X_ = R * np.linspace(-1, 1, échantillonnage)

La variable X couvre le diamètre du cercle le long de l'horizontale, de gauche à droite, ce qui signifie de –R à +R. Maintenant tu peux t'entraîner y:

y_ = np.sqrt(R ** 2 - X_ ** 2)

Le tableau y_ est la version discrète de la variable continue y, qui décrit un cercle. Vous pouvez tracer ces points à l'aide d'un nuage de points:

importer matplotlib.pyplot comme plt

plt.dispersion(X_, y_)
plt.axe("carré")
plt.montrer()

Pour vous assurer que le tracé bidimensionnel présente le motif correct, définissez les axes sur "carré", ce qui garantit que chaque pixel a un rapport hauteur / largeur carré:

Points de la planète en orbite semi-circulaire

Tous les points s'emboîtent bien sur la circonférence d'un cercle, ce qui devrait être le cas pour une planète en orbite circulaire.

Mais les planètes ne tournent pas seulement autour d’une orbite semi-circulaire. Le problème est que les valeurs de X pour l'autre moitié du cercle sont les mêmes. Le demi-cercle du haut et celui du bas partagent le même X valeurs mais pas les mêmes y valeurs.

Vous pouvez résoudre ce problème en regardant en arrière l'équation ci-dessus qui donne y en terme de X. Cette équation a à la fois une solution positive et une solution négative. Comme X revient de +R à droite de –R à gauche, vous pouvez prendre la solution négative pour y:

# x_return et y_return sont les valeurs x_ et y_ comme
# planète se déplace de droite à gauche
x_return = X_[[[[len(X_)-2:0:-1]
y_return = -np.sqrt(R ** 2 - x_return ** 2)

X_ = np.enchaîner((X_, x_return))
y_ = np.enchaîner((y_, y_return))

Le tableau x_return est l'inverse de X_ mais sans les points de terminaison. Sinon, les points de terminaison seront répétés lors de la concaténation X_ et x_return. Le tableau y_return est la solution négative pour y_. Par conséquent, vous pouvez écraser X_ devenir la concaténation de X_ et x_return:

>>>

>>> X_
tableau ([-50-4795918367-4591836735-4387755102[-50-4795918367-4591836735-4387755102[-50-4795918367-4591836735-4387755102[-50-4795918367-4591836735-4387755102
                            -41.83673469, -39.79591837, -37.75510204, -35.71428571,
                            -33.67346939, -31.63265306, -29.59183673, -27.55102041,
                            -25.51020408, -23.46938776, -21.42857143, -19.3877551,
                            -17.34693878, -15.30612245, -13.26530612, -11.2244898,
                                -9.18367347, -7.14285714, -5.10204082, -3.06122449,
                                -1.02040816, 1.02040816, 3.06122449, 5.10204082,
                                    7.14285714, 9.18367347, 11.2244898, 13.26530612,
                                15.30612245, 17.34693878, 19.3877551, 21.42857143,
                                23.46938776, 25.51020408, 27.55102041, 29.59183673,
                                31.63265306, 33.67346939, 35.71428571, 37.75510204,
                                39.79591837, 41.83673469, 43.87755102, 45.91836735,
                                47.95918367, 50., 47.95918367, 45.91836735,
                                43.87755102, 41.83673469, 39.79591837, 37.75510204,
                                35.71428571, 33.67346939, 31.63265306, 29.59183673,
                                27.55102041, 25.51020408, 23.46938776, 21.42857143,
                                19.3877551, 17.34693878, 15.30612245, 13.26530612,
                                11.2244898, 9.18367347, 7.14285714, 5.10204082,
                                    3.06122449, 1.02040816, -1.02040816, -3.06122449,
                                -5.10204082, -7.14285714, -9.18367347, -11.2244898,
                            -13.26530612, -15.30612245, -17.34693878, -19.3877551,
                            -21.42857143, -23.46938776, -25.51020408, -27.55102041,
                            -29.59183673, -31.63265306, -33.67346939, -35.71428571,
                            -37.75510204, -39.79591837, -41.83673469, -43.87755102,
                            -45.91836735, -47.95918367])

Les valeurs à l'intérieur X_ aller de -50 par 0 à 50 puis de retour 0 à -50. Vous pouvez également imprimer y_ pour confirmer qu'il correspond aux valeurs positives de y pour la première moitié et les valeurs négatives de y pour la seconde moitié. Un nuage de points de X_ et y_ confirmera que la planète est maintenant sur une orbite qui fait un cercle complet:

plt.dispersion(X_, y_)
plt.axe("carré")
plt.montrer()

Cela donne le tracé suivant:

Échantillonnage incorrect des points de la planète en orbite circulaire

Vous pourrez peut-être déjà repérer le problème dans ce nuage de points, mais vous y reviendrez un peu plus tard. Pour l'instant, vous pouvez utiliser le X_ et y_ ci-dessus pour créer une simulation de la planète en mouvement.

Vous devrez importer matplotlib.animation pour ça:

importer matplotlib.animation

# Créez une figure et une poignée d'axe, définissez l'axe sur
# un aspect égal (carré), et désactivez les axes
figure, hache = plt.sous-parcelles()
hache.set_aspect("égal")
hache.set_axis_off()

# Les images sont générées et stockées dans une liste pour être animées plus tard
images = []
pour x_coord, y_coord dans Zip *: français(X_, y_):
    # Scatter plot chaque point en utilisant un point de taille 250 et de couleur rouge
    img = hache.dispersion(x_coord, y_coord, s=250, c="r")
    # Mettons aussi un grand soleil jaune au milieu
    img2 = hache.dispersion(0, 0, s=1000, c="y")
    images.ajouter([[[[img, img2])

# L'animation peut maintenant être créée avec ArtistAnimation
animation = matplotlib.animation.ArtisteAnimation(figure,
                                                 images,
                                                 intervalle=2,5,
                                                 blit=Vrai
                                                 )
plt.montrer()

Cela donne la sortie suivante:

Animation de la planète en orbite

Malheureusement, les planètes ne tournent pas de cette manière. Vous pouvez voir comment la planète accélère lorsqu'elle traverse l'axe des x à gauche et à droite de l'orbite et ralentit lorsqu'elle traverse l'axe des y en haut et en bas.

Jetez un autre coup d'œil aux nuages ​​de points montrant toutes les positions des planètes autour de l'orbite pour voir pourquoi cela se produit. Les points sont plus rapprochés en haut et en bas de l'orbite mais espacés à gauche et à droite. Vous avez besoin de points régulièrement espacés sur la circonférence de l'orbite, mais ce que vous avez, ce sont des points basés sur un espacement régulier. X_ vecteur.

Pour résoudre ce problème, vous devez créer un tableau de X_ des valeurs qui ne sont pas linéaires mais qui produisent des points linéaires le long de la circonférence de l'orbite. Lorsqu'un point se déplace doucement autour d'une orbite circulaire, sa projection sur l'axe x se déplace (co-) sinusoïdalement, vous pouvez donc résoudre ce problème en X_ de sorte qu'il soit linéaire sur cos (x_):

X_ = R * np.cos(np.linspace(-np.pi, 0, échantillonnage))
x_return = X_[[[[len(X_)-2: 0: -1]

y_ = np.sqrt(R ** 2 - X_ ** 2)
y_return = -np.sqrt(R ** 2 - x_return ** 2)

X_ = np.enchaîner((X_, x_return))
y_ = np.enchaîner((y_, y_return))

plt.dispersion(X_, y_)
plt.axe("carré")
plt.montrer()

La première ligne transforme un espace linéaire en un espace non linéaire. Les intervalles entre chaque valeur de X_ ne sont pas égaux mais varient en fonction de la fonction cosinus. Cela donne le tracé suivant:

Échantillonnage correct des points de la planète en orbite circulaire

Les points sont maintenant régulièrement espacés sur la circonférence de l'orbite circulaire. Votre dernière étape consiste à recréer l'animation en utilisant le même code que précédemment. C'est également le bon moment pour augmenter la résolution en augmentant la valeur du échantillonnage variable que vous avez définie au début:

échantillonnage = 250

# ...

figure, hache = plt.sous-parcelles()
hache.set_aspect("égal")
hache.set_axis_off()

images = []
pour x_coord, y_coord dans Zip *: français(X_, y_):
    img = hache.dispersion(x_coord, y_coord, s=250, c="r")
    img2 = hache.dispersion(0, 0, s=1000, c="y")
    images.ajouter([[[[img, img2])

animation = matplotlib.animation.ArtisteAnimation(figure,
                                                 images,
                                                 intervalle=2,5,
                                                 blit=Vrai
                                                 )
plt.montrer()

Cela donne la sortie suivante:

Animation de la planète en orbite dans NumPy

Pour voir la version complète du code qui génère cette animation, vous pouvez développer la section ci-dessous.

La version complète et finale de la simulation, y compris l'enregistrement de la simulation dans un .gif, est disponible ici:

    1importer matplotlib.animation
    2importer matplotlib.pyplot comme plt
    3importer engourdi comme np
    4
    5échantillonnage = 250
    6R = 50
    sept
    8# Créer un vecteur x_ linéaire sur cos (x_)
    9# Créez d'abord x_ de gauche à droite (-R vers + R)
dixX_ = R * np.cos(np.linspace(-np.pi, 0, échantillonnage))
11# Et puis x_ revient de droite à gauche (+ R vers R)
12x_return = X_[[[[len(X_)-2: 0: -1]
13
14# Calculer y_ en utilisant la solution positive lorsque x_ augmente
15y_ = np.sqrt(R ** 2 - X_ ** 2)
16# Et la solution négative lorsque x_ diminue
17y_return = -np.sqrt(R ** 2 - x_return ** 2)
18
19X_ = np.enchaîner((X_, x_return))
20y_ = np.enchaîner((y_, y_return))
21
22# Créer une animation
23figure, hache = plt.sous-parcelles()
24hache.set_aspect("égal")
25hache.set_axis_off()
26
27images = []
28pour x_coord, y_coord dans Zip *: français(X_, y_):
29    img = hache.dispersion(x_coord, y_coord, s=250, c="r")
30    img2 = hache.dispersion(0, 0, s=1000, c="y")
31    images.ajouter([[[[img, img2])
32
33animation = matplotlib.animation.ArtisteAnimation(figure,
34                                                 images,
35                                                 intervalle=2,5,
36                                                 blit=Vrai
37                                                 )
38plt.montrer()
39
40# Exporter vers .gif
41écrivain = matplotlib.animation.Oreiller(images par seconde=30)
42animation.enregistrer("orbiting_planet_simulation.gif", écrivain=écrivain)

Vous venez de créer une animation d’une planète en orbite autour d’une étoile. Vous deviez rendre le mouvement de la planète linéaire sur la circonférence d'un cercle en faisant les positions de la planète uniformément espacées sur la circonférence du cercle. Vous pouvez désormais créer n'importe quelle plage de nombres non espacée de manière uniforme, à condition de pouvoir l'exprimer mathématiquement.