08 NumPy Flashcards
import numpy as np
import panda as pd
padrão na comunidade Python
a1D = np.array([1, 2, 3])
a1D
»»»>
array([1, 2, 3])
O objeto criado é um ndarray: n-dimensional array #
type(a1D)
»»»
numpy.ndarray
a1D.dtype >>>>>>> dtype('int32') # na aula foi int64, não sei pq #
b1D = np.array ( [1, 2, 3], dtype = float) print(b1D) b1D.dtype >>>>>> [1. 2. 3.] dtype('float64') # poderia ser str
d1D = np.array([1, 3.14, "NumPy", True]) d1D >>>>>>> array(['1', '3.14', 'NumPy', 'True'], dtype='>>>>>> array([1. , 3.14, 0. , 1. ])
ndarray suporta somente um único de dado
se misturar na hora de criar a ndarray, Python vai criar de acordo com:
str>float>int>bool
ndarrays de mais de 1 dimensão
2 dimensões (linha x coluna)
a2D = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9]]) a2D >>>>>>> array ( [ [ 1, 2, 3], [4, 5, 6], [7, 8, 9 ] ] )
3 dimensões (linha x coluna x face/página)
a3D = np.array( [ [ [1,2,3], [4,5,6], [7,8,9] ], [ [11,12,13], [14,15,16], [17,18,19] ], [ [21,22,23], [24,25,26], [27,28,29] ]])
a3D
»»»»»
array( [ [ [ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9] ],
[ [11, 12, 13], [14, 15, 16], [17, 18, 19] ], [ [21, 22, 23], [24, 25, 26], [27, 28, 29] ] ] )
# 3 dimensões czeros = np.zeros((3, 4, 2)) # 3 páginas, 4 linhas e 2 colunas czeros >>>>>>>>> array([[[0., 0.], [0., 0.], [0., 0.], [0., 0.]],
[[0., 0.], [0., 0.], [0., 0.], [0., 0.]], [[0., 0.], [0., 0.], [0., 0.], [0., 0.]]])
poderia colocar dtype pra escolher outro tipo
dzeros = np.zeros((2, 3, 4), dtype = str)
dzeros
»»»>
array([[[’’, ‘’, ‘’, ‘’],
[’’, ‘’, ‘’, ‘’],
[’’, ‘’, ‘’, ‘’]],
[['', '', '', ''], ['', '', '', ''], ['', '', '', '']]], dtype='
4 dimensões
f_um_4D = np.ones((2, 4, 2, 3), dtype=bool)
f_um_4D
»»»»
1D
Linha
2D
Linha x Coluna
3D
Página x Linha x Coluna
4D
Vetor de Cubos (?)
etc…
array([[[[ True, True, True],
[ True, True, True]],
[[ True, True, True], [ True, True, True]], [[ True, True, True], [ True, True, True]], [[ True, True, True], [ True, True, True]]], [[[ True, True, True], [ True, True, True]], [[ True, True, True], [ True, True, True]], [[ True, True, True], [ True, True, True]], [[ True, True, True], [ True, True, True]]]])
ndarrays vs listas normais do Python?
ndarrays são muito mais rápidas
a1D = np.arange(10)
a1D
»»»>
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
b1D = np.arange(5, 15)
b1D
»»»>
array([ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
c1D = np.arange(5,100, 10)
c1D
»»»>
array([ 5, 15, 25, 35, 45, 55, 65, 75, 85, 95])
d1D = np.linspace(0,10, 2) # Cria um array com 2 valores entre 0 e 10
d1D
»»»»>
array([ 0., 10.])
e1D = np.linspace(0,10, 4) # Cria um array com 2 valores entre 0 e 10
e1D
»»»»>
array([ 0. , 3.33333333, 6.66666667, 10. ])
g1D = np.linspace(1,1000, dtype = int)
g1D
»»»»»»
array([ 1, 21, 41, 62, 82, 102, 123, 143, 164, 184, 204, 225, 245, 266, 286, 306, 327, 347, 367, 388, 408, 429, 449, 469, 490, 510, 531, 551, 571, 592, 612, 633, 653, 673, 694, 714, 734, 755, 775, 796, 816, 836, 857, 877, 898, 918, 938, 959, 979, 1000])
# Se não for passada a quantidade de elementos, o padrão é gerar 50 elementos
# gerando int, a função simplesmente corta as casas decimais (ou seja, arredonda sempre para baixo)
h1D = np.linspace(0,50, 10, endpoint = True, dtype=int)
h1D
»»»»»
array([ 0, 5, 11, 16, 22, 27, 33, 38, 44, 50])
# O valor final é incluído
i1D = np.linspace(0,50, 10, endpoint = False, dtype=int)
i1D
»»»»>
array([ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45])
# O valor final não é incluído
# ndarray contendo 10 números 5 a1D = np.full(10, 5) a1D >>>>>>> array([5, 5, 5, 5, 5, 5, 5, 5, 5, 5])
# ndarray de 3 linhas e 5 colunas contendo o número 3 a2D = np.full((3, 5), 3) a2D >>>>>>> array([[3, 3, 3, 3, 3], [3, 3, 3, 3, 3], [3, 3, 3, 3, 3]])
# ndarray de 2 páginas, 3 linhas e 4 colunas contendo o número -1 a3D = np.full((2, 3, 4), -1) a3D >>>>>>>> array([[[-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1]],
[[-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1]]])
# Cria uma matriz 5x5 preenchida com 1s na diagonal principal e 0 nas posições restantes ident = np.eye(5) ident >>>>>>>> array([[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.], [0., 0., 1., 0., 0.], [0., 0., 0., 1., 0.], [0., 0., 0., 0., 1.]])
Cria um ndarray com 10 elementos entre 0 e 99
a1D = np.random.randint(0, 100, 10)
a1D
»»»>
array([90, 82, 66, 5, 82, 84, 17, 18, 10, 5])
a2D = np.random.randint(1, 500, (4,5)) a2D >>>>>>> array([[325, 394, 186, 400, 438], [ 35, 98, 61, 139, 71], [476, 86, 437, 280, 474], [295, 390, 72, 441, 309]])
# Gerando 10 combinações para a mega-sena # Valores vão de 1 a 60, 10 páginas, 1 linha, 6 colunas a3D = np.random.randint(1,61,(10,1,6)) a3D >>>>>>>> array([[[ 4, 12, 51, 43, 4, 26]], [[20, 58, 27, 32, 36, 36]], [[40, 53, 24, 60, 39, 12]], [[49, 21, 11, 5, 10, 31]], [[35, 35, 31, 14, 19, 39]], [[ 2, 10, 46, 23, 45, 15]], [[41, 15, 41, 58, 28, 33]], [[20, 7, 56, 38, 6, 50]], [[20, 37, 36, 3, 45, 47]], [[14, 37, 33, 41, 55, 55]]])
# Cria um ndarray de 3 linhas e 2 colunas contendo elementos aleatórios entre 0 e 1 c2D = np.random.random((3,2)) c2D >>>>>>>>> array([[0.30789558, 0.8570651 ], [0.41280201, 0.00804518], [0.73345547, 0.01438448]])
# Cria um ndarray de 2 páginas x 4 linhas x 5 colunas com elementos entre 1 e 100 a3D = np.random.randint(1, 101, (2,4,5)) a3D >>>>>>>> array([[[ 22, 32, 15, 77, 71], [ 87, 72, 58, 37, 41], [ 74, 22, 32, 87, 14], [ 75, 25, 61, 34, 2]],
[[ 92, 75, 20, 49, 38], [ 67, 2, 51, 100, 4], [ 23, 47, 2, 4, 94], [ 56, 52, 32, 66, 79]]])
a3D.shape
»»»»>
(2,4,5)
a3D.ndim
»»»»>
3
a3D.size
»»»»
40
Retorna o tamanho da 1a dimensão (quantidade de páginas)
len(a3D)
»»»»
2
Retorna o tamanho da 2a dimensão (quantidade de linhas)
len(a3D[0])
»»»»
4
Retorna o tamanho da 3a dimensão (quantidade de colunas)
len(a3D[0][0])
»»»»
5
a3D.dtype
»»»»
dtype(‘int32’)
a3D.dtype.name
»»»»
‘int32’
# Cria um ndarray de 2 páginas x 4 linhas x 5 colunas com elementos entre 1 e 100 a3D = np.random.randint(1, 101, (2,4,5)) a3D >>>>>>>>> array([[[86, 49, 14, 68, 47], [68, 43, 45, 6, 1], [56, 89, 63, 92, 99], [39, 29, 55, 96, 89]],
[[68, 76, 11, 6, 71], [97, 28, 85, 23, 91], [31, 85, 79, 27, 21], [47, 35, 11, 55, 67]]])
nome_do_cubo[página][linha][coluna]
a3D[1][0][3]
»»»>
6
a3D[0][3][1]
»»»>
29
indice_pag = [0, 1, 1, 1] indice_lin = [0, 1, 2, 3] indice_col = [3, 2, 1, 0] a3D[indice_pag, indice_lin, indice_col] >>>>>>>>> array([68, 85, 85, 47])
# Cria um ndarray de 4 linhas x 5 colunas com elementos entre 1 e 100 a2D = np.random.randint(1, 101, (4,5)) a2D >>>>>>>> array([[89, 75, 92, 15, 90], [22, 12, 25, 74, 79], [99, 43, 6, 17, 66], [73, 57, 21, 17, 37]])
a2D[:,[0,1,2,0]] >>>>>>>>> array([[89, 75, 92, 89], [22, 12, 25, 22], [99, 43, 6, 99], [73, 57, 21, 73]]) # pega todas as linhas (:) # pega os elementos nas colunas 0, 1, 2 e 0 em cada uma delas, em ordem
a2D [ : , [ 0,1,2,0 ] ] [ [ 1, 0, 1, 0 ] ] == a2D [ [ 1, 0, 1, 0 ] ] [ : , [0,1,2,0] ] >>>>>>>>> array([[22, 12, 25, 22], [89, 75, 92, 89], [22, 12, 25, 22], [89, 75, 92, 89]]) # pega todas as linhas # pega os elementos 0,1,2,0 das linhas 1,0,1,0 nessa ordem
a3D >>>>>>>>> array([[[86, 49, 14, 68, 47], [68, 43, 45, 6, 1], [56, 89, 63, 92, 99], [39, 29, 55, 96, 89]],
[[68, 76, 11, 6, 71], [97, 28, 85, 23, 91], [31, 85, 79, 27, 21], [47, 35, 11, 55, 67]]])
subface1 = a3D[1 , 0:3 , 1:4] subface1 >>>>>>>> array([[76, 11, 6], [28, 85, 23], [85, 79, 27]]) # face 1, linha 0, 1 e 2, coluna 1, 2 e 3
invertido = a3D[::-1, ::-1, ::-1] invertido >>>>>>>> array([[[67, 55, 11, 35, 47], [21, 27, 79, 85, 31], [91, 23, 85, 28, 97], [71, 6, 11, 76, 68]],
[[89, 96, 55, 29, 39], [99, 92, 63, 89, 56], [ 1, 6, 45, 43, 68], [47, 68, 14, 49, 86]]])
# Cria um ndarray de 4 linhas x 5 colunas com elementos entre 1 e 100 a2D = np.random.randint(1, 101, (4, 5)) a2D >>>>>>>> array([[29, 39, 49, 91, 28], [47, 56, 27, 73, 74], [86, 83, 51, 29, 35], [97, 60, 22, 91, 23]])
a2D >= 50
»»»»>
array([[False, False, False, True, False],
[False, True, False, True, True],
[ True, True, True, False, False],
[ True, True, False, True, False]])
# retorna se é True or False a comparação
a2D[a2D >= 50]
»»»»>
array([91, 56, 73, 74, 86, 83, 51, 97, 60, 91])
# retorna os valores em que é verdadeiro
a2D.mean ( )
»»»
54.5
# retorna a média
a2D[a2D <= a2D.mean()]
»»»»
array([29, 39, 49, 28, 47, 27, 51, 29, 35, 22, 23])
# retorna o que é menor do que a média
a3D = np.random.randint(1,200, (2,3,6)) a3D >>>>>>>>>> array([[[194, 117, 99, 175, 134, 162], [149, 19, 128, 10, 130, 17], [ 25, 24, 198, 143, 184, 122]],
[[160, 37, 187, 197, 194, 79], [ 16, 127, 78, 191, 69, 147], [ 64, 102, 179, 106, 138, 184]]])
a3D[1][2][4] = -1 a3D >>>>>>> array([[[194, 117, 99, 175, 134, 162], [149, 19, 128, 10, 130, 17], [ 25, 24, 198, 143, 184, 122]],
[[160, 37, 187, 197, 194, 79], [ 16, 127, 78, 191, 69, 147], [ 64, 102, 179, 106, -1, 184]]])
a3D_modificado = np.append(a3D, [100, 130])
a3D_modificado
»»»»»
array([194, 117, 99, 175, 134, 162, 149, 19, 128, 10, 130, 17, 25,
24, 198, 143, 184, 122, 160, 37, 187, 197, 194, 79, 16, 127,
78, 191, 69, 147, 64, 102, 179, 106, -1, 184, 100, 130])
# Lineariza a3D e insere os elementos no final
a3D = np.random.randint(1,200, (2,3,6)) a3D >>>>> array([[[ 17, 118, 37, 34, 121, 120], [ 24, 81, 58, 128, 144, 122], [ 73, 156, 187, 133, 34, 191]],
[[ 69, 86, 192, 146, 80, 163], [ 58, 92, 8, 172, 162, 70], [ 39, 168, 143, 89, 140, 49]]])
a3D_modificado2 = np.delete(a3D, [0, 1, 3])
print(a3D_modificado2)
»»»»
[ 37 121 120 24 81 58 128 144 122 73 156 187 133 34 191 69 86 192
146 80 163 58 92 8 172 162 70 39 168 143 89 140 49]
a1D = np.array([1, 2, 3, 4, 5]) b1D = np.array([3, 2, 1, 4, 5]) a1D == b1D >>>>>> array([False, True, False, True, True]) # Comparação elemento a elemento
c1D = np.random.randint(1,3,10)
c1D
»»»
array([1, 2, 1, 2, 1, 1, 2, 2, 1, 2])
c1D == 1
»»»
array([ True, False, True, False, True, True, False, False, True,
False])
c1D[c1D == 1]
»»»>
array([1, 1, 1, 1, 1])
celsius = np.arange(-20, 46, 5) fahrenheit = celsius * (9/5) + 32 fahrenheit >>>>> array([ -4., 5., 14., 23., 32., 41., 50., 59., 68., 77., 86., 95., 104., 113.])
g1D = a1D + b1D print(a1D) print(b1D) print("-"*31) print(g1D) >>>>>> [ 1 2 3 4 5 6 7 8 9 10] [ 1 3 5 7 9 11 13 15 17 19] ------------------------------- [ 2 5 8 11 14 17 20 23 26 29] # Equivalente a h1D = np.add(a1D, b1D) # ainda existe .subtract , .multiply , . divide , .sqrt (raiz quadrada)
d2D >>>>>>> array([[73, 97, 50, 20], [43, 17, 96, 68], [20, 24, 4, 78], [43, 69, 61, 61], [11, 99, 67, 63]])
d2D.sum()
»»»>
1064
somacol = sum(d2D) somacol >>>>> array([190, 306, 278, 290]) #função do Python, não NumPy
d2D.sum(axis = 0)
»»»
array([190, 306, 278, 290])
d2D.sum(axis = 1)
»»»
array([240, 224, 126, 234, 240])
d2D >>>>>>> array([[73, 97, 50, 20], [43, 17, 96, 68], [20, 24, 4, 78], [43, 69, 61, 61], [11, 99, 67, 63]])
d2D.sum()
»»»>
1064
somacol = sum(d2D) somacol >>>>> array([190, 306, 278, 290]) #função do Python, não NumPy
d2D.sum(axis = 0)
»»»
array([190, 306, 278, 290])
d2D.sum(axis = 1)
»»»
array([240, 224, 126, 234, 240])
d2D.min()
d2D == array([[73, 97, 50, 20], [43, 17, 96, 68], [20, 24, 4, 78], [43, 69, 61, 61], [11, 99, 67, 63]])
4
array([11, 17, 4, 20])
array([20, 17, 4, 43, 11])
mesmo raciocínio pra .max ( )
d2D.mean()
d2D.cumsum(axis = 0) == array([[ 73, 97, 50, 20], [116, 114, 146, 88], [136, 138, 150, 166], [179, 207, 211, 227], [190, 306, 278, 290]], dtype=int32)
53.2
61.0
#coincidiu de ter 2 vezes o 61 e esse ser a mediana, mas se tiver numero par, soma as duas “semi-medianas” e divide por 2 corretamente
28.739519828974178
a2D = np.random.randint(1,50, (4,5)) a2D == array([[ 8, 36, 31, 25, 2], [30, 40, 48, 42, 14], [48, 22, 49, 7, 17], [17, 9, 44, 31, 2]])
c2D = a2D c2D == array([[ 8, 36, 31, 25, 2], [30, 40, 48, 42, 14], [48, 22, 49, 7, 17], [17, 9, 44, 31, 2]])
c2D[c2D < 20] = -1 c2D == array([[-1, 36, 31, 25, -1], [30, 40, 48, 42, -1], [48, 22, 49, -1, -1], [-1, -1, 44, 31, -1]])
a2D == array([[-1, 36, 31, 25, -1], [30, 40, 48, 42, -1], [48, 22, 49, -1, -1], [-1, -1, 44, 31, -1]])
PARA FAZER A CÓPIA DE VERDADE
c2D = a2D.copy()
c2D
a2D = np.random.randint(1,100, (3,5)) a2D == array([[89, 51, 29, 75, 3], [ 6, 72, 96, 70, 70], [33, 16, 41, 38, 92]])
a2D.sort(axis=0) # Ordenando pelo eixo 0 (colunas) a2D == array([[ 3, 29, 38, 41, 89], [ 6, 33, 51, 72, 92], [16, 70, 70, 75, 96]])
a2D.sort() a2D == array([[ 3, 29, 51, 75, 89], [ 6, 70, 70, 72, 96], [16, 33, 38, 41, 92]]) # Por padrão ordena o maior eixo (1 > 0) #nesse caso o eixo 1, linhas
x = a2D
np.sort(x) == array([[ 3, 29, 51, 75, 89], [ 6, 70, 70, 72, 96], [16, 33, 38, 41, 92]])
-np.sort(-x) == array([[89, 41, 38, 29, 3], [92, 72, 51, 33, 6], [96, 75, 70, 70, 16]])
SORT DESCENDING
TRANSPOSIÇÃO DE ARRAYS
a2D = np.array([[1,2,3,4],[5,6,7,8]]) a2D == array([[1, 2, 3, 4], [5, 6, 7, 8]])
Retornar a transposta
a2DT = a2D.T a2DT == array([[1, 5], [2, 6], [3, 7], [4, 8]])
a2D.transpose ( ) == array([[1, 5], [2, 6], [3, 7], [4, 8]])
MUDANDO O FORMATO DE ARRAY
a1D = np.arange(1,13) print(a1D) #1 print(a1D.shape) # a1D.shape = (2,6) print(a1D.shape) #3 print(a1D) #4 == [ 1 2 3 4 5 6 7 8 9 10 11 12] # 1 (12,) # 2 (2, 6) # 3 [[ 1 2 3 4 5 6] # 4 [ 7 8 9 10 11 12]] # 4
a2D_4x6 = a1D.reshape(4,3) a2D_4x6 == array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9], [10, 11, 12]])
# .shape altera o formato # .reshape só altera naquela hora (não global)
LINEARIZAÇÃO DE ARRAY(3 ou mais dimensões)
a2D = a1D.reshape(4,3) a2D == array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9], [10, 11, 12]])
x = a2D.flatten()
x
==
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
y = a2D.ravel()
y
==
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
ravel() does not occupy memory so we can say that it is faster than flatten()
If you try to modify the flattened view then you end up with that same change in the original array.
Changes made to flattened array is not reflected back to the original array.
flatten() occupies memory so it is considered slower than ravel() function.
a2D: 3 x 5
array([[24, 14, 53, 88, 79],
[71, 96, 6, 65, 46],
[29, 55, 14, 42, 13]])
b2D: 4 x 5 array([[77, 57, 99, 20, 93], [61, 44, 90, 82, 13], [70, 59, 96, 76, 69], [92, 30, 69, 33, 7]])
c2D: 4 x 3 array([[13, 4, 55], [86, 82, 65], [65, 58, 14], [53, 91, 94]])
# Concatenando pelo eixo das colunas (eixo 0) (empilhamento vertical) # número de colunas deve ser igual A = np.concatenate((a2D, b2D), axis = 0) print(A) == [[24 14 53 88 79] [71 96 6 65 46] [29 55 14 42 13] [77 57 99 20 93] [61 44 90 82 13] [70 59 96 76 69] [92 30 69 33 7]] #.concatenate = .vstack se for por colunas (vertical stack)
Concatenando pelo eixo das linhas (eixo 1) (empilhamento horizontal)
# número de linhas deve ser igual
C = np.concatenate((b2D, c2D), axis = 1)
print(“b2D”)
==
[[77 57 99 20 93 13 4 55]
[61 44 90 82 13 86 82 65]
[70 59 96 76 69 65 58 14]
[92 30 69 33 7 53 91 94]]
# .concatenate = hstack se for por linhas (horizontal stack)
Divisão vertical (corta no sentido das colunas)
A_splitted = np.vsplit(D,2) print("Array original") print(A) print("") print("1a parte") print(A_splitted[0]) print("") print("2a parte") print(A_splitted[1])
==
Array original [[24 14 53 88 79] [71 96 6 65 46] [29 55 14 42 13] [77 57 99 20 93] [61 44 90 82 13] [70 59 96 76 69] [92 30 69 33 7]]
1a parte
[[77 57 99 20 93 13 4 55]
[61 44 90 82 13 86 82 65]]
2a parte
[[70 59 96 76 69 65 58 14]
[92 30 69 33 7 53 91 94]]
Divisão horizontal (corta no sentido das linhas)
A_splitted3 = np.hsplit(C,2) print("Array original") print(A) print("") print("1a parte") print(A_splitted3[0]) print("") print("2a parte") print(A_splitted3[1])
==
Array original [[24 14 53 88 79] [71 96 6 65 46] [29 55 14 42 13] [77 57 99 20 93] [61 44 90 82 13] [70 59 96 76 69] [92 30 69 33 7]]
1a parte [[77 57 99 20] [61 44 90 82] [70 59 96 76] [92 30 69 33]]
2a parte [[93 13 4 55] [13 86 82 65] [69 65 58 14] [ 7 53 91 94]]
%timeit soma(idades)
## custom Python func
2.38 s ± 77.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit sum(idades)
## standard Python func
2.01 s ± 33.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.sum(idades)
## NumPy func
9.26 ms ± 1.42 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
Reparar que nas duas funções do Python estamos trabalhando com SEGUNDOS
No NumPy é MILISSEGUNDOS
NUMPY é muito mais rápido!!!
Em outro exemplo, tudo na ordem de segundos (1.3 a 1.9), ordem pelo tempo mais rápido ao mais lento:
def quad_comprehension(numeros): return [num * num for num in numeros]
def quadrado(numeros): quadrados = [] for num in numeros: quadrados.append(num * num) return quadrados
def quad_map(numeros): return list(map(lambda num: num * num, numeros))
def quadrado2(numeros): quadrados = [] for num in numeros: quadrados.append(num ** 2) return quadrados
Agora exemplos no Numpy:
%timeit np.power(numeros,2)
28.7 ms ± 712 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit list(np.power(numeros,2))
473 ms ± 2.47 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
ou seja, pra criar lista o NumPy é só 2.5-3 vezes mais rápido