Positions et tranches, maintenant en plusieurs dimensions
Les tableaux s'indexent comme les listes : a[0] est le premier élément, a[-1] le dernier et a[début:fin:pas] une tranche qui s'arrête avant fin. La différence est qu'un tableau peut avoir plusieurs dimensions, et l'on donne un indice ou une tranche par dimension, séparés par des virgules : m[ligne, colonne]. Un : seul veut dire « toute cette dimension » : m[:, 1] est toute la deuxième colonne et m[1] (ou m[1, :]) toute la deuxième ligne. Les nombres négatifs comptent depuis la fin, et un pas de -1 inverse.
import numpy as np
a = np.array([10., 11., 12., 13., 14., 15.])
print(a[0], a[-1]) # 10.0 15.0
print(a[1:4]) # [11. 12. 13.]
print(a[-2:]) # [14. 15.]
print(a[::2]) # [10. 12. 14.]
print(a[::-1]) # [15. 14. 13. 12. 11. 10.]
# Two dimensions: one index or slice per dimension
m = np.arange(12).reshape(3, 4)
print(m[1, 2]) # 6
print(m[:, 1]) # [1 5 9] the whole second column
print(m[-1, :]) # [ 8 9 10 11] the last row
print(m[0:2, 1:3]) # [[1 2]
# [5 6]]Les tranches sont des vues, pas des copies
Contrairement à une tranche de liste, une tranche simple NumPy ne copie pas les données : c'est une vue sur la même mémoire, donc écrire à travers elle modifie le tableau d'origine. Cela rend le découpage instantané même pour d'énormes tableaux, mais surprend : part = a[1:4]; part[0] = 99 modifie aussi a[1]. Quand il faut un tableau indépendant, appelez .copy(). On peut vérifier avec np.shares_memory(a, b). Le même comportement de vue vaut pour les lignes, colonnes, pas et tranches inversées.
import numpy as np
a = np.array([10., 11., 12., 13., 14., 15.])
part = a[1:4] # a view, no data copied
part[0] = 99
print(a) # [10. 99. 12. 13. 14. 15.] a changed too
safe = a[1:4].copy() # an independent array
safe[0] = -1
print(a) # [10. 99. 12. 13. 14. 15.] unchanged
print(np.shares_memory(a, a[::2])) # True
print(np.shares_memory(a, safe)) # FalseMasques booléens et listes d'indices
Comparer un tableau donne un tableau de booléens de même taille : r > 0 vaut True là où le rendement est positif. En utilisant ce masque comme indice, r[r > 0], on ne garde que ces éléments. Combinez les conditions avec & (et), | (ou) et ~ (non), chaque condition entre parenthèses, car les and/or de Python ne fonctionnent pas sur les tableaux. Une liste ou un tableau d'entiers convient aussi, a[[0, 2, 5]], qui prend exactement ces positions dans cet ordre. La sélection par masque ou par liste d'indices copie les données, et l'on peut aussi affecter à travers un masque : a[a > 3] = 0.
import numpy as np
r = np.array([0.01, -0.02, 0.03, -0.01, 0.0, 0.02])
print(r > 0) # [ True False True False False True]
print(r[r > 0]) # [0.01 0.03 0.02]
print(r[(r > 0) & (r < 0.025)]) # [0.01 0.02] parentheses are required
print(np.where(r > 0)[0]) # [0 2 5] positions where it holds
# Pick by position, in any order
w = np.array([3.0, 9.0, 1.0, 7.0])
order = np.argsort(-w) # positions from the largest value down
print(order[:2], w[order[:2]]) # [1 3] [9. 7.]
# Assign through a mask
counts = np.array([1, 2, 3, 4, 5, 6])
counts[counts > 3] = 0
print(counts) # [1 2 3 0 0 0]import numpy as np
# Rows are days, columns are assets (AAPL, MSFT, GOOG)
R = np.array([[ 0.02, -0.01, 0.03],
[ 0.01, 0.00, 0.02],
[-0.03, 0.02, -0.01],
[ 0.00, 0.01, 0.04]])
print(R[:, [0, 2]]) # the AAPL and GOOG columns, as a copy
print(R[R[:, 0] > 0]) # the days on which AAPL rose (whole rows)
print(R[R[:, 0] > 0].shape) # (2, 3)
print(R[-2:, 1].mean()) # 0.015 last two days of MSFTa[1:4], m[:, 1], a[::2]) sont des vues ; les masques et listes d'indices (a[a > 0], a[[0, 2]]) sont des copies. Une fonction qui renvoie une tranche de son argument donne à l'appelant une fenêtre sur ses propres données, si bien qu'une écriture ultérieure peut les modifier de façon inattendue. Décidez en connaissance de cause : renvoyez une vue quand la vitesse compte et que les données sont en lecture seule, sinon .copy(). Les tests du lab vérifient les deux comportements.- Un indice ou une tranche par dimension :
m[ligne, col],m[:, 1](une colonne),m[-1](dernière ligne),a[::-1]. - Les tranches simples sont des vues (les écritures se répercutent ;
.copy()pour détacher) ; masques et listes d'indices font des copies. - Masques :
a[a > 0], combinés avec&,|,~entre parenthèses ;np.argsortdonne les positions dans l'ordre trié.
À suivre : la vectorisation, qui remplace les boucles Python par de l'arithmétique sur des tableaux entiers.
Lab : ce qui est noté
- Prendre les lignes les plus récentes avec
last_rows25 pts - Ne garder que les gains avec
positive_values25 pts - Échantillonner une valeur sur k avec
every_kth25 pts - Trouver les positions des k plus grandes valeurs avec
top_k_indices25 pts