Python de cero a experto: Numpy
Contents
Python de cero a experto: Numpy#
Autor: Luis Miguel de la Cruz Salas
Python de cero a experto by Luis M. de la Cruz Salas is licensed under Attribution-NonCommercial-NoDerivatives 4.0 International
Objetivo general
Conocer a fondo las ventajas de la biblioteca Numpy.
Objetivos particulares
Identificar algunas de las funciones más usadas de la biblioteca Numpy.
Hacer énfasis en los métodos y conceptos que se aprenderán y en algunas cuestiones computacionales.
Contenido#
Numpy#
Es una biblioteca de Python que permite crear y gestionar arreglos multidimensionales, junto con una gran colección de funciones matemáticas de alto nivel que operan sobre estos arreglos. El sitio oficial es https://numpy.org/
Para usar todas las herramientas de numpy debemos importar la biblioteca como sigue:
import numpy as np
np.version.version
'1.21.5'
# Función para obtener los atributos de arreglos
info_array = lambda x: print(f' tipo : {type(x)} \n dtype : {x.dtype} \n dim : {x.ndim} \n shape : {x.shape} \n size(bytes) : {x.itemsize} \n size(elements) : {x.size}')
Creación de arreglos simples#
Crear un arreglo de números del 1 al 10 usando:
np.array
, np.arange
, np.linspace
, np.zeros
, np.ones
, np.random.rand
x = np.array([1,2,3,4,5,6,7,8,9,10])
x
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 1
shape : (10,)
size(bytes) : 4
size(elements) : 10
x = np.arange(10)
x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
x = np.arange(1,11,1)
x
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 1
shape : (10,)
size(bytes) : 4
size(elements) : 10
Ojo np.arange()
acepta parámetros flotantes:
xf = np.arange(1, 11, 1.0)
xf
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
info_array(xf)
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 1
shape : (10,)
size(bytes) : 8
size(elements) : 10
xf = np.arange(0.3, 0.7, 0.12)
xf
array([0.3 , 0.42, 0.54, 0.66])
x = np.linspace(1,10,10)
x
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 1
shape : (10,)
size(bytes) : 8
size(elements) : 10
Ojo: con np.linspace
es posible generar un número exacto de elementos, por ejemplo:
xf = np.linspace(0.3, 0.7, 6)
xf
array([0.3 , 0.38, 0.46, 0.54, 0.62, 0.7 ])
x = np.zeros(10)
x
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
for i,val in enumerate(x):
x[i] = i+1
x
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 1
shape : (10,)
size(bytes) : 8
size(elements) : 10
x = np.ones(10)
x
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 1
shape : (10,)
size(bytes) : 8
size(elements) : 10
for i,val in enumerate(x):
x[i] = i+val
x
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
x *= 2
x
array([ 2., 4., 6., 8., 10., 12., 14., 16., 18., 20.])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 1
shape : (10,)
size(bytes) : 8
size(elements) : 10
x = np.random.rand(10)
info_array(x)
x
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 1
shape : (10,)
size(bytes) : 8
size(elements) : 10
array([0.95264144, 0.0307895 , 0.70781213, 0.86148072, 0.95815789,
0.4442273 , 0.61359623, 0.99906471, 0.80411922, 0.48092923])
x = np.random.rand(2,5)
info_array(x)
x
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 2
shape : (2, 5)
size(bytes) : 8
size(elements) : 10
array([[0.14520303, 0.97016093, 0.55601282, 0.77542234, 0.143609 ],
[0.19220465, 0.36647977, 0.53623488, 0.06378879, 0.18409342]])
Nota sobre número pseudoaleatorios#
No es posible generar números aleatorios con base en un algoritmo, solo se pueden obtener números pseudoaleatorios (para obtener números aleatorios es necesario muestrear algún parámetro físico cuyo valor sea realmente aleatorio).
Las series de números aleatorios que se pueden generar en una computadora son secuencias deterministas a partir de un valor inicial, al que se llama semilla. Al fijar la semilla se fija completamente los valores de toda la serie.
np.random.seed(0)
print("Serie 1:", np.random.rand(3))
np.random.seed(3)
print("Serie 2:", np.random.rand(3))
np.random.seed(0)
print("Serie 3:", np.random.rand(3))
Serie 1: [0.5488135 0.71518937 0.60276338]
Serie 2: [0.5507979 0.70814782 0.29090474]
Serie 3: [0.5488135 0.71518937 0.60276338]
Se puede generar una serie de números aleatorios usando una semilla aleatoria. Por ejemplo:
import time
np.random.seed(int(time.time()))
np.random.rand(3)
array([0.27741954, 0.43947286, 0.67275793])
Modificar el tipo de dato de los elementos del arreglo#
x = np.linspace(1,10,10)
# La modificación afecta al arreglo 'y' pero no al arreglo 'x' (no es inplace)
y = x.astype(int)
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 1
shape : (10,)
size(bytes) : 8
size(elements) : 10
info_array(y)
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 1
shape : (10,)
size(bytes) : 4
size(elements) : 10
print(id(x), id(y))
3035013915152 3035013915056
print(x)
print(y)
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1 2 3 4 5 6 7 8 9 10]
Arreglos multidimensionales#
x = np.array([[1,2.0],[0,0],(1+1j,3.)])
x
array([[1.+0.j, 2.+0.j],
[0.+0.j, 0.+0.j],
[1.+1.j, 3.+0.j]])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : complex128
dim : 2
shape : (3, 2)
size(bytes) : 16
size(elements) : 6
x = np.array( [ [1,2], [3,4] ], dtype=complex )
x
array([[1.+0.j, 2.+0.j],
[3.+0.j, 4.+0.j]])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : complex128
dim : 2
shape : (2, 2)
size(bytes) : 16
size(elements) : 4
x = np.array( [ [[1,2], [3,4]], [[5,6], [7,8]] ])
x
array([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 3
shape : (2, 2, 2)
size(bytes) : 4
size(elements) : 8
x = np.zeros((10,10))
x
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., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 2
shape : (10, 10)
size(bytes) : 8
size(elements) : 100
x = np.ones((4,3,2))
x
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.]]])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 3
shape : (4, 3, 2)
size(bytes) : 8
size(elements) : 24
x = np.empty((2,3,4))
x
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.]]])
info_array(x)
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 3
shape : (2, 3, 4)
size(bytes) : 8
size(elements) : 24
Cambiando el shape
de los arreglos#
Función reshape
#
x = np.array([ [[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9,10,11,12]],
[[13,14,15,16],
[17,16,19,20],
[21,22,23,24]] ])
info_array(x)
print(f'x = \n {x}')
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 3
shape : (2, 3, 4)
size(bytes) : 4
size(elements) : 24
x =
[[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[13 14 15 16]
[17 16 19 20]
[21 22 23 24]]]
y = x.reshape(6,4)
info_array(y)
print(f'y = \n {y}')
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 2
shape : (6, 4)
size(bytes) : 4
size(elements) : 24
y =
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]
[17 16 19 20]
[21 22 23 24]]
info_array(x)
print(f'x = \n {x} \n')
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 3
shape : (2, 3, 4)
size(bytes) : 4
size(elements) : 24
x =
[[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[13 14 15 16]
[17 16 19 20]
[21 22 23 24]]]
y = x.reshape(24)
info_array(y)
print(f'y = \n {y}')
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 1
shape : (24,)
size(bytes) : 4
size(elements) : 24
y =
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 16 19 20 21 22 23 24]
y = x.reshape(2,3,4)
info_array(y)
print(f'y = \n {y}')
print(f'x = \n {x}')
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 3
shape : (2, 3, 4)
size(bytes) : 4
size(elements) : 24
y =
[[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[13 14 15 16]
[17 16 19 20]
[21 22 23 24]]]
x =
[[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[13 14 15 16]
[17 16 19 20]
[21 22 23 24]]]
# Otra manera
np.reshape(x, (6,4))
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16],
[17, 16, 19, 20],
[21, 22, 23, 24]])
x
array([[[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]],
[[13, 14, 15, 16],
[17, 16, 19, 20],
[21, 22, 23, 24]]])
Atributo shape
(inplace)#
y.shape
(2, 3, 4)
y.shape = (6,4)
y.shape
(6, 4)
info_array(y)
print(f'y = \n {y}')
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 2
shape : (6, 4)
size(bytes) : 4
size(elements) : 24
y =
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]
[17 16 19 20]
[21 22 23 24]]
Creando un arreglo y modificando su shape
al vuelo#
x = np.arange(24).reshape(2,3,4)
x
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
x = np.arange(1,25,1).reshape(2,3,4)
info_array(x)
x
tipo : <class 'numpy.ndarray'>
dtype : int32
dim : 3
shape : (2, 3, 4)
size(bytes) : 4
size(elements) : 24
array([[[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]],
[[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]]])
Copias y vistas de arreglos#
x = np.array([1,2,3,4])
z = x # z es un sinónimo de x, no se crea una copia!
print(id(z), id(x))
print(z is x)
print(x is z)
3035013730000 3035013730000
True
True
Los objetos que son mutables se pasan por referencia a una función:
def f(a):
print(id(a))
print(id(x))
print(f(x))
3035013730000
3035013730000
None
Copia superficial o vista de un arreglo#
z = x.view()
print(id(z), id(x))
print(z is x)
print(x is z)
print(z.base is x) # Comparten la memoria
print(z.flags.owndata) # Propiedades de la memoria
print(x.flags.owndata) # Propiedades de la memoria
3035013882192 3035013730000
False
False
True
False
True
print(z.flags)
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
z.shape =(2,2)
print(z.shape, z, sep = '\n')
print(x.shape, x, sep = '\n')
(2, 2)
[[1 2]
[3 4]]
(4,)
[1 2 3 4]
z[1,1] = 1000
print(z.shape, z, sep = '\n')
print(x.shape, x, sep = '\n')
(2, 2)
[[ 1 2]
[ 3 1000]]
(4,)
[ 1 2 3 1000]
Copia completa de arreglos#
z = x.copy()
print(id(z), id(x))
print(z is x)
print(x is z)
print(z.base is x) # Comparten la memoria
print(z.flags.owndata) # Propiedades de la memoria
print(x.flags.owndata) # Propiedades de la memoria
3035014003856 3035013730000
False
False
False
True
True
print('z = ', z)
print('x = ', x)
z = [ 1 2 3 1000]
x = [ 1 2 3 1000]
z[3] = 4
print('z = ', z)
print('x = ', x)
z = [1 2 3 4]
x = [ 1 2 3 1000]
Las rebanadas son vistas de arreglos#
Las vistas de arreglos pueden ser útiles en ciertos casos, por ejemplo si tenemos un arreglo muy grande y solo deseamos mantener unos cuantos elementos del mismo, debemos hacer lo siguiente:
a = np.arange(int(1e5)) # Arreglo de 100000 elementos
b = a[:200].copy() # Copia completa de 200 elementos de 'a'
del a # Eliminar la memoria que usa 'a'
b
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
195, 196, 197, 198, 199])
Pero si usamos rebanadas, el comportamiento es distinto:
a = np.arange(int(1e5)) # Arreglo de 100000 elementos
b = a[:200] # Vista de 200 elementos de 'a'
b[0] = 1000
print('b = ', b)
print('a = ', a)
b = [1000 1 2 3 4 5 6 7 8 9 10 11 12 13
14 15 16 17 18 19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36 37 38 39 40 41
42 43 44 45 46 47 48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79 80 81 82 83
84 85 86 87 88 89 90 91 92 93 94 95 96 97
98 99 100 101 102 103 104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119 120 121 122 123 124 125
126 127 128 129 130 131 132 133 134 135 136 137 138 139
140 141 142 143 144 145 146 147 148 149 150 151 152 153
154 155 156 157 158 159 160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175 176 177 178 179 180 181
182 183 184 185 186 187 188 189 190 191 192 193 194 195
196 197 198 199]
a = [ 1000 1 2 ... 99997 99998 99999]
Rebanadas (slicing)#
x = np.arange(0,10,1.)
x
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
x[:] # El arreglo completo
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
x[3:6] # Una sección del arreglo, de 3 a 5
array([3., 4., 5.])
x[2:9:2] # de 2 a 8, dando saltos de 2 en 2
array([2., 4., 6., 8.])
x[1:7:2] = 100 # modificando algunos elementos del arreglo
x
array([ 0., 100., 2., 100., 4., 100., 6., 7., 8., 9.])
y = np.arange(36).reshape(6,6)
y
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35]])
y[1:4,:] # renglones de 1 a 3
array([[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
y[:,1:5] # columnas de 1 a 4
array([[ 1, 2, 3, 4],
[ 7, 8, 9, 10],
[13, 14, 15, 16],
[19, 20, 21, 22],
[25, 26, 27, 28],
[31, 32, 33, 34]])
y[2:4,2:5] # seccion del arreglo
array([[14, 15, 16],
[20, 21, 22]])
y[1:5:2,1:5:2] # sección del arreglo
# con saltos de 2
array([[ 7, 9],
[19, 21]])
y[1:5:2,1:5:2] = 0 # Modificación de
y # algunos elementos
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 0, 8, 0, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 0, 20, 0, 22, 23],
[24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35]])
También es posible seleccionar elementos que cumplan cierto criterio.
y[y<25] # Selecciona los elementos del arreglo que son menores que 25
array([ 0, 1, 2, 3, 4, 5, 6, 0, 8, 0, 10, 11, 12, 13, 14, 15, 16,
17, 18, 0, 20, 0, 22, 23, 24])
y[y%2==0] # Selecciona todos los elementos pares
array([ 0, 2, 4, 6, 0, 8, 0, 10, 12, 14, 16, 18, 0, 20, 0, 22, 24,
26, 28, 30, 32, 34])
y[(y>8) & (y<20)] # Selecciona todos los elementos mayores que 8 y menores que 20
array([10, 11, 12, 13, 14, 15, 16, 17, 18])
y[(y>8) & (y<20)] = 666
y
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 0, 8, 0, 666, 666],
[666, 666, 666, 666, 666, 666],
[666, 0, 20, 0, 22, 23],
[ 24, 25, 26, 27, 28, 29],
[ 30, 31, 32, 33, 34, 35]])
z = np.nonzero(y == 666) # Determina los renglones y las columnas
z # donde se cumple la condición.
(array([1, 1, 2, 2, 2, 2, 2, 2, 3], dtype=int64),
array([4, 5, 0, 1, 2, 3, 4, 5, 0], dtype=int64))
z[0]
z[1]
array([4, 5, 0, 1, 2, 3, 4, 5, 0], dtype=int64)
indices = list(zip(z[0], z[1])) # Genera una lista de coordenadas donde se cumple la condición.
indices
[(1, 4), (1, 5), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (3, 0)]
print(y[z]) # Imprime los elementos del arreglo 'y' usando las coordenadas de 'z'
[666 666 666 666 666 666 666 666 666]
Operaciones básicas entre arreglos#
v1 = np.array([2.3,3.1,9.6])
v2 = np.array([3.4,5.6,7.8])
(1/3)*v1 # Escalar por arreglo
array([0.76666667, 1.03333333, 3.2 ])
v1+v2 # Suma de arreglos
array([ 5.7, 8.7, 17.4])
v1-v2 # Resta de arreglos
array([-1.1, -2.5, 1.8])
v1*v2 # Multiplicación elemento a elemento
array([ 7.82, 17.36, 74.88])
v1/v2 # División elemento a elemento
array([0.67647059, 0.55357143, 1.23076923])
v1 ** 2 # Potencia de un arreglo
array([ 5.29, 9.61, 92.16])
v1 % 2 # Modulo de un arreglo
array([0.3, 1.1, 1.6])
10 * np.sin(v1) # Aplicación de una función matemática a cada elemento del arreglo
array([ 7.45705212, 0.41580662, -1.74326781])
v1 > 3 # Operación de comparación, devuelve un arreglo Booleano
array([False, True, True])
Operaciones entre arreglos Booleanos#
f = np.array([True, False, False, True])
r = np.array([False, True, False, True])
f & r
array([False, False, False, True])
f | r
array([ True, True, False, True])
~f
array([False, True, True, False])
b = np.arange(4)
b
array([0, 1, 2, 3])
b[f]
array([0, 3])
b[f] = 100
b
array([100, 1, 2, 100])
Métodos de los arreglos#
Existe una larga lista de métodos definidos para los arreglos, vea más información aquí.
x = np.random.random(100) # arreglo de 100 números aleatorios entre 1 y 0
x
array([0.87291136, 0.4667654 , 0.70839531, 0.11684876, 0.61010161,
0.7147785 , 0.85947455, 0.41154746, 0.20367318, 0.24597665,
0.42261173, 0.91721399, 0.72011719, 0.91370418, 0.26290151,
0.03459652, 0.66887324, 0.46283526, 0.5203149 , 0.00208701,
0.11384754, 0.27872633, 0.62833527, 0.59686206, 0.89216901,
0.4018794 , 0.05253424, 0.3615654 , 0.58458147, 0.02306903,
0.62590551, 0.26816266, 0.0862259 , 0.30367739, 0.70024002,
0.56309863, 0.1705416 , 0.63663901, 0.88721368, 0.39898073,
0.02959757, 0.83432856, 0.61962458, 0.2100619 , 0.59540551,
0.59486019, 0.68973324, 0.46701423, 0.84454763, 0.24243676,
0.43177763, 0.46203364, 0.68622725, 0.14122981, 0.50100177,
0.63985902, 0.14659953, 0.28232146, 0.0509266 , 0.93795137,
0.64457388, 0.2156847 , 0.70847786, 0.36213372, 0.96756227,
0.96529352, 0.35240117, 0.04446743, 0.29282926, 0.44647528,
0.48893531, 0.94065941, 0.03167257, 0.22116515, 0.43616742,
0.16834263, 0.53048185, 0.60647013, 0.51353945, 0.83722147,
0.26796455, 0.88329564, 0.44291643, 0.38710391, 0.02580616,
0.80157481, 0.64949162, 0.13565818, 0.66619073, 0.59266059,
0.38782264, 0.19657226, 0.40097001, 0.14446758, 0.86432544,
0.15629524, 0.13793043, 0.87147767, 0.80171914, 0.26516875])
x.max()
0.9675622714985623
x.sum()
46.97148771826547
x = np.arange(10).reshape(2,5)
x
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
x.T
array([[0, 5],
[1, 6],
[2, 7],
[3, 8],
[4, 9]])
x.transpose()
array([[0, 5],
[1, 6],
[2, 7],
[3, 8],
[4, 9]])
np.transpose(x)
array([[0, 5],
[1, 6],
[2, 7],
[3, 8],
[4, 9]])
np.flip(x) # Cambiar el orden de los elementos del arreglo
array([[9, 8, 7, 6, 5],
[4, 3, 2, 1, 0]])
np.flip(x, axis=0)
array([[5, 6, 7, 8, 9],
[0, 1, 2, 3, 4]])
f1 = x.flatten() # Aplanar un arreglo
f1[0] = 1000
print(x)
print(f1)
[[0 1 2 3 4]
[5 6 7 8 9]]
[1000 1 2 3 4 5 6 7 8 9]
print(x)
[[0 1 2 3 4]
[5 6 7 8 9]]
f2 = x.ravel() # Aplanar un arreglo
f2[0] = 1000
print(x)
print(f1)
[[1000 1 2 3 4]
[ 5 6 7 8 9]]
[1000 1 2 3 4 5 6 7 8 9]
Los arreglos deben ser compatibles para poder realizar las operaciones anteriores:
a = np.arange(24).reshape(2,3,4)
b = np.arange(24).reshape(2,3,4)
a + b
array([[[ 0, 2, 4, 6],
[ 8, 10, 12, 14],
[16, 18, 20, 22]],
[[24, 26, 28, 30],
[32, 34, 36, 38],
[40, 42, 44, 46]]])
c = np.arange(24).reshape(6,4)
a + c
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_13860\4122427811.py in <module>
1 c = np.arange(24).reshape(6,4)
----> 2 a + c
ValueError: operands could not be broadcast together with shapes (2,3,4) (6,4)
Apilación y concatenación de arreglos#
a = np.arange(4).reshape(2,2)
b = np.arange(4,8,1).reshape(2,2)
print(a)
print(b)
[[0 1]
[2 3]]
[[4 5]
[6 7]]
np.vstack( (a, b) ) # Apilación vertical
array([[0, 1],
[2, 3],
[4, 5],
[6, 7]])
np.hstack( (a, b) ) # Apilación horizontal
array([[0, 1, 4, 5],
[2, 3, 6, 7]])
x = np.arange(1,25,1).reshape(6,4)
x
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]])
np.hsplit(x, 2) # División vertical en dos arreglos
[array([[ 1, 2],
[ 5, 6],
[ 9, 10],
[13, 14],
[17, 18],
[21, 22]]),
array([[ 3, 4],
[ 7, 8],
[11, 12],
[15, 16],
[19, 20],
[23, 24]])]
np.vsplit(x, 2) # División horizontal en dos arreglos
[array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]]),
array([[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]])]
Se recomienda revisar la función np.concatenate
para ver más opciones
Agregando dimensiones al arreglo#
x = np.arange(1,11,1.)
info_array(x)
x
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 1
shape : (10,)
size(bytes) : 8
size(elements) : 10
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
x.T
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
x_row = x[np.newaxis, :]
info_array(x_row)
x_row
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 2
shape : (1, 10)
size(bytes) : 8
size(elements) : 10
array([[ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]])
x_row.T
array([[ 1.],
[ 2.],
[ 3.],
[ 4.],
[ 5.],
[ 6.],
[ 7.],
[ 8.],
[ 9.],
[10.]])
x_col = x[:, np.newaxis]
info_array(x_col)
x_col
tipo : <class 'numpy.ndarray'>
dtype : float64
dim : 2
shape : (10, 1)
size(bytes) : 8
size(elements) : 10
array([[ 1.],
[ 2.],
[ 3.],
[ 4.],
[ 5.],
[ 6.],
[ 7.],
[ 8.],
[ 9.],
[10.]])
# Otra manera
x_row = np.expand_dims(x, axis=0)
x_col = np.expand_dims(x, axis=1)
print(x_row)
print(x_col)
[[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]]
[[ 1.]
[ 2.]
[ 3.]
[ 4.]
[ 5.]
[ 6.]
[ 7.]
[ 8.]
[ 9.]
[10.]]
Constantes#
np.e
2.718281828459045
np.euler_gamma # Euler–Mascheroni constant
0.5772156649015329
np.pi
3.141592653589793
np.inf # Infinito
inf
#Por ejemplo
np.array([1]) / 0.
/tmp/ipykernel_24865/3182226453.py:2: RuntimeWarning: divide by zero encountered in divide
np.array([1]) / 0.
array([inf])
np.nan # Not a Number: Valor no definido o no representable
nan
# Por ejemplo
np.sqrt(-1)
/tmp/ipykernel_24865/1910582514.py:2: RuntimeWarning: invalid value encountered in sqrt
np.sqrt(-1)
nan
np.log([-1, 1, 2])
/tmp/ipykernel_24865/55426429.py:1: RuntimeWarning: invalid value encountered in log
np.log([-1, 1, 2])
array([ nan, 0. , 0.69314718])
np.NINF # Infinito negativo
-inf
# Por ejemplo
np.array([-1]) / 0.
/tmp/ipykernel_24865/3889258382.py:2: RuntimeWarning: divide by zero encountered in divide
np.array([-1]) / 0.
array([-inf])
np.NZERO # Cero negativo
-0.0
np.PZERO # Cero positivo
0.0
Exportando e importando arreglos a archivos#
x = np.arange(1,25,1.0).reshape(6,4)
print(x)
np.savetxt('arreglo.csv', x, fmt='%.2f', delimiter=',', header='1, 2, 3, 4')
[[ 1. 2. 3. 4.]
[ 5. 6. 7. 8.]
[ 9. 10. 11. 12.]
[13. 14. 15. 16.]
[17. 18. 19. 20.]
[21. 22. 23. 24.]]
xf = np.loadtxt('arreglo.csv', delimiter=',')
xf
array([[ 1., 2., 3., 4.],
[ 5., 6., 7., 8.],
[ 9., 10., 11., 12.],
[13., 14., 15., 16.],
[17., 18., 19., 20.],
[21., 22., 23., 24.]])
#Usando la biblioteca Pandas
import pandas as pd
df = pd.DataFrame(x)
df
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 1.0 | 2.0 | 3.0 | 4.0 |
1 | 5.0 | 6.0 | 7.0 | 8.0 |
2 | 9.0 | 10.0 | 11.0 | 12.0 |
3 | 13.0 | 14.0 | 15.0 | 16.0 |
4 | 17.0 | 18.0 | 19.0 | 20.0 |
5 | 21.0 | 22.0 | 23.0 | 24.0 |
df.to_csv('arreglo_PD.csv')
y = pd.read_csv('arreglo_PD.csv')
y
Unnamed: 0 | 0 | 1 | 2 | 3 | |
---|---|---|---|---|---|
0 | 0 | 1.0 | 2.0 | 3.0 | 4.0 |
1 | 1 | 5.0 | 6.0 | 7.0 | 8.0 |
2 | 2 | 9.0 | 10.0 | 11.0 | 12.0 |
3 | 3 | 13.0 | 14.0 | 15.0 | 16.0 |
4 | 4 | 17.0 | 18.0 | 19.0 | 20.0 |
5 | 5 | 21.0 | 22.0 | 23.0 | 24.0 |