NumPy

De Wikipedia, la enciclopedia libre
NumPy
Información general
Tipo de programa Software de análisis numérico
Autor Travis Oliphant
Desarrollador Proyecto comunitario
Lanzamiento inicial 1995
Licencia Nueva Licencia BSD[2]
Información técnica
Programado en
Versiones
Última versión estable 1.26.2 ( 20 de noviembre de 2023[1]​)
Archivos legibles
numpy
Archivos editables
numpy
Enlaces

NumPy (pronunciado /ˈnʌmp/ (numpai) o, a veces /ˈnʌmpi/[3][4]​ (numpi)) es una biblioteca para el lenguaje de programación Python que da soporte para crear vectores y matrices grandes multidimensionales, junto con una gran colección de funciones matemáticas de alto nivel para operar con ellas. El precursor de NumPy, Numeric, fue creado originalmente por Jim Hugunin con contribuciones de varios otros desarrolladores. En 2005, Travis Oliphant creó NumPy incorporando características de la competencia Numarray en Numeric, con amplias modificaciones. NumPy es un software de código abierto y cuenta con muchos colaboradores.

Historia[editar]

El lenguaje de programación Python no fue diseñado originalmente para computación numérica, pero atrajo la atención de la comunidad científica y de ingeniería desde el principio. En 1995 se fundó el grupo de interés especial (SIG) matrix-sig con el objetivo de definir un paquete de computación de vectores; entre sus miembros se encontraba el diseñador y mantenedor de Python Guido van Rossum, quien extendió la sintaxis de Python (en particular la sintaxis de indexación) para facilitar la computación de vectores.[5]

Jim Fulton completó una implementación de un paquete para matrices, luego generalizado por Jim Hugunin y llamado Numeric (también conocido como las "extensiones numéricas de Python" o "NumPy"). Hugunin, estudiante de posgrado en el Instituto de Tecnología de Massachusetts (MIT), : 10 se unió a la Corporación para Iniciativas de Investigación Nacional (CNRI) en 1997 para trabajar en JPython, dejando a Paul Dubois del Laboratorio Nacional Lawrence Livermore (LLNL) para asumir el cargo de mantenedor. : 10 Otros colaboradores tempranos incluyen a David Ascher, Konrad Hinsen y Travis Oliphant. : 10 

Se escribió un nuevo paquete llamado Numarray como reemplazo más flexible de Numeric.[6]​ Al igual que Numeric, actualmente también está obsoleto.[7][8]​ Numarray tenía operaciones más rápidas para matrices grandes, pero era más lento que Numeric para las pequeñas,[9]​ por lo que durante un tiempo ambos paquetes se usaron en paralelo para diferentes casos de uso. La última versión de Numeric (v24.2) se publicó el 11 de noviembre de 2005, mientras que la última versión de Numarray (v1.5.2) se publicó el 24 de agosto de 2006.[10]

Había un deseo de incluir Numeric en la biblioteca estándar de Python, pero Guido van Rossum decidió que el código no se podía mantener en su estado en ese momento. [¿cuándo?][11]​ A principios de 2005, el desarrollador de NumPy, Travis Oliphant, quería unificar la comunidad en torno a un solo paquete de arreglo y portó las características de Numarray a Numeric, lanzando el resultado como NumPy 1.0 en 2006.[6]​ Este nuevo proyecto formaba parte de SciPy. Para evitar instalar el gran paquete SciPy solo para obtener un objeto de matriz, este nuevo paquete se separó y se llamó NumPy. El soporte para Python 3 se añadió en 2011 con la versión 1.5.0 de NumPy.[12]

En 2011, PyPy comenzó a desarrollar una implementación de la API NumPy para PyPy.[13]​ Todavía no es totalmente compatible con NumPy.[14]

Características[editar]

NumPy apunta a la implementación de Python de referencia CPython, un intérprete de código de bytes no optimizador. Los algoritmos matemáticos escritos para esta versión de Python a menudo se ejecutan mucho más lento que los equivalentes compilados. NumPy aborda el problema de la lentitud en parte al proporcionar matrices multidimensionales, funciones y operadores que operan de manera eficiente en matrices, lo que requiere reescribir algo de código, principalmente bucles internos, usando NumPy.

El uso de NumPy en Python brinda una funcionalidad comparable a MATLAB, ya que ambos se interpretan,[15]​ y ambos permiten al usuario escribir programas rápidos siempre que la mayoría de las operaciones funcionen en vectores o matrices en lugar de escalares. En comparación, MATLAB cuenta con una gran cantidad de cajas de herramientas adicionales, en particular Simulink, mientras que NumPy está intrínsecamente integrado con Python, un lenguaje de programación más moderno y completo. Además, se encuentran disponibles paquetes complementarios de Python; SciPy es una biblioteca que agrega más funcionalidad similar a MATLAB y Matplotlib es un paquete de trazado que proporciona una funcionalidad de trazado similar a MATLAB. Internamente, tanto MATLAB como NumPy se basan en BLAS y LAPACK para cálculos de álgebra lineal eficientes.

Los bindings de Python de la ampliamente utilizada biblioteca de visión por computadora OpenCV utilizan matrices NumPy para almacenar y operar con datos. Dado que las imágenes con múltiples canales se representan simplemente como matrices tridimensionales, indexar, cortar o enmascarar con otras matrices son formas muy eficientes de acceder a píxeles específicos de una imagen. La matriz NumPy como estructura de datos universal en OpenCV para imágenes, puntos de características extraídos, núcleos de filtrado y muchos más simplifica enormemente el flujo de trabajo de programación y la depuración .

La estructura de datos ndarray[editar]

La funcionalidad principal de NumPy es su estructura de datos "ndarray", para una matriz de n dimensiones. Estas matrices son vistas escalonadas de la memoria.[6]​ A diferencia de la estructura de datos de lista incorporada de Python, estas matrices se escriben de forma homogénea: todos los elementos de una única matriz deben ser del mismo tipo.

Dichas matrices también pueden ser vistas en búferes de memoria asignados por extensiones de C o C++, Cython y Fortran al intérprete CPython sin la necesidad de copiar datos, lo que brinda un mayor grado de compatibilidad con las bibliotecas numéricas existentes. Esta funcionalidad es explotada por el paquete SciPy, que incluye varias de estas bibliotecas (en particular BLAS y LAPACK). NumPy tiene soporte incorporado para ndarrays mapeados en memoria.[6]

Limitaciones[editar]

Insertar o agregar entradas a una matriz no es tan trivialmente posible como lo es con las listas de Python. La rutina np.pad(...) para extender matrices crea nuevas matrices con la forma deseada y los valores de relleno, copia la matriz dada en la nueva y la devuelve. La operación np.concatenate([a1, a2])de NumPy no vincula realmente las dos matrices, sino que devuelve una nueva, llena con las entradas de ambas matrices dadas en secuencia. La remodelación de las dimensiones de una matriz con np.reshape(...) solo es posible siempre que el número de elementos de la matriz no cambie. Estas circunstancias se originan en el hecho de que las matrices de NumPy deben ser vistas en búferes de memoria contiguos. Un paquete de reemplazo llamado Blaze intenta superar esta limitación.[16]

Los algoritmos que no se pueden expresar como una operación vectorizada normalmente se ejecutarán lentamente porque deben implementarse en "Python puro", mientras que la vectorización puede aumentar la complejidad de la memoria de algunas operaciones de constante a lineal, porque se deben crear matrices temporales que sean tan grandes como las entradas. Varios grupos han implementado la compilación en tiempo de ejecución de código numérico para evitar estos problemas. Las soluciones de código abierto que interactúan con NumPy incluyen scipy.weave, numexpr[17]​ y Numba.[18]Cython y Pythran son otras alternativas de compilación estática.

Ejemplos[editar]

Creación de matrices
>>> import numpy as np
>>> x = np.array([1, 2, 3])
>>> x
array([1, 2, 3])
>>> y = np.arange(10)  # como en Python list(range(10)), pero devuelve una matriz de numpy
>>> y
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Operaciones básicas
>>> a = np.array([1, 2, 3, 6])
>>> b = np.linspace(0, 2, 4)  # crea un vector con cuatro puntos equiespaciados, desde 0 hasta 2.
>>> c = a - b
>>> c
array([ 1.        ,  1.33333333,  1.66666667,  4.        ])
>>> a**2
array([ 1,  4,  9, 36])
Funciones universales
>>> a = np.linspace(-np.pi, np.pi, 100) 
>>> b = np.sin(a)
>>> c = np.cos(a)
Álgebra lineal
>>> from numpy.random import rand
>>> from numpy.linalg import solve, inv
>>> a = np.array([[1, 2, 3], [3, 4, 6.7], [5, 9.0, 5]])
>>> a.transpose()
array([[ 1. ,  3. ,  5. ],
       [ 2. ,  4. ,  9. ],
       [ 3. ,  6.7,  5. ]])
>>> inv(a)
array([[-2.27683616,  0.96045198,  0.07909605],
       [ 1.04519774, -0.56497175,  0.1299435 ],
       [ 0.39548023,  0.05649718, -0.11299435]])
>>> b =  np.array([3, 2, 1])
>>> solve(a, b)  # resuelve la ecuación ax = b
array([-4.83050847,  2.13559322,  1.18644068])
>>> c = rand(3, 3) * 20  # crea una matriz de 3x3 con valores aleatorios en el intervalo [0,1] escalados por 20
>>> c
array([[  3.98732789,   2.47702609,   4.71167924],
       [  9.24410671,   5.5240412 ,  10.6468792 ],
       [ 10.38136661,   8.44968437,  15.17639591]])
>>> np.dot(a, c)  # multiplicación de matrices
array([[  53.61964114,   38.8741616 ,   71.53462537],
       [ 118.4935668 ,   86.14012835,  158.40440712],
       [ 155.04043289,  104.3499231 ,  195.26228855]])
>>> a @ c # notación alternativa desde Python 3.5 y NumPy 1.10
array([[  53.61964114,   38.8741616 ,   71.53462537],
       [ 118.4935668 ,   86.14012835,  158.40440712],
       [ 155.04043289,  104.3499231 ,  195.26228855]])
Tensores
>>> M = np.zeros(shape=(2, 3, 5, 7, 11))
>>> T = np.transpose(M, (4, 2, 1, 3, 0))
>>> T.shape
(11, 5, 3, 7, 2)
Incorporación con OpenCV
>>> import numpy as np
>>> import cv2
>>> r = np.reshape(np.arange(256*256)%256,(256,256))  # matriz de píxeles 256x256 con un gradiente horizontal de 0 a 255, para el canal del color rojo
>>> g = np.zeros_like(r)  # matriz del mismo tamaño que r pero rellena de ceros, para el canal del color verde
>>> b = r.T # matriz r traspuesta que genera un gradiente vertical, para el canal del color azul
>>> cv2.imwrite('gradients.png', np.dstack([b,g,r]))  # las imágenes OpenCV se interpretan como BGR, la matriz agrupada se escribirá en un archivo PNG de 8 bit llamado 'gradients.png'
True
Búsqueda Nearest-Neighbor: algoritmo de Python iterativo y versión vectorizada de NumPy
>>> # # # Python iterativo puro # # #
>>> points = [[9,2,8],[4,7,2],[3,4,4],[5,6,9],[5,0,7],[8,2,7],[0,3,2],[7,3,0],[6,1,1],[2,9,6]]
>>> qPoint = [4,5,3]
>>> minIdx = -1
>>> minDist = -1
>>> for idx, point in enumerate(points):  # itera sobre todos los puntos
        dist = sum([(dp-dq)**2 for dp,dq in zip(point,qPoint)])**0.5  # calcula la distancia euclídea desde cada punto a q
        if dist < minDist or minDist < 0:  # si se requiere, actualiza la distancia mínima y el índice del punto correspondiente
            minDist = dist
            minIdx = idx

>>> print('Punto más cercano a q: {0}'.format(points[minIdx]))
Punto más cercano a q: [3, 4, 4]

>>> # # # Vectorización equivalente en NumPy # # #
>>> import numpy as np
>>> points = np.array([[9,2,8],[4,7,2],[3,4,4],[5,6,9],[5,0,7],[8,2,7],[0,3,2],[7,3,0],[6,1,1],[2,9,6]])
>>> qPoint = np.array([4,5,3])
>>> minIdx = np.argmin(np.linalg.norm(points-qPoint,axis=1))  # calcula todas las distancias euclídeas de una vez y devuelve el índice de la menor de ellas
>>> print('Punto más cercano a q: {0}'.format(points[minIdx]))
Punto más cercano a q: [3 4 4]

Véase también[editar]

Referencias[editar]

  1. «Releases – numpy/numpy». Consultado el 7 de diciembre de 2023 – via GitHub. 
  2. «NumPy — NumPy». numpy.org. NumPy developers. 
  3. Pine, David (2014). «Python resources». Rutgers University. Consultado el 7 de abril de 2017. 
  4. «How do you say numpy?». Reddit. 2015. Consultado el 7 de abril de 2017. 
  5. Millman, K. Jarrod; Aivazis, Michael (2011). «Python for Scientists and Engineers». Computing in Science and Engineering 13 (2): 9-12. 
  6. a b c d van der Walt, Stéfan; Colbert, S. Chris; Varoquaux, Gaël (2011). «The NumPy array: a structure for efficient numerical computation». Computing in Science and Engineering (IEEE). Bibcode:2011arXiv1102.1523V. arXiv:1102.1523. 
  7. «Numarray Homepage». Consultado el 24 de junio de 2006. 
  8. Travis E. Oliphant (7 de diciembre de 2006). Guide to NumPy. Consultado el 2 de febrero de 2017. 
  9. Travis Oliphant and other SciPy developers. «[Numpy-discussion] Status of Numeric». Archivado desde el original el 3 de febrero de 2017. Consultado el 2 de febrero de 2017. 
  10. «NumPy Sourceforge Files». Consultado el 24 de marzo de 2008. 
  11. «History_of_SciPy - SciPy wiki dump». scipy.github.io. 
  12. «NumPy 1.5.0 Release Notes». Consultado el 29 de abril de 2011. 
  13. «PyPy Status Blog: NumPy funding and status update». Consultado el 22 de diciembre de 2011. 
  14. «NumPyPy Status». Consultado el 14 de octubre de 2013. 
  15. The SciPy Community. «NumPy for Matlab users». Consultado el 2 de febrero de 2017. 
  16. «Blaze Ecosystem Docs». Read the Docs. Consultado el 17 de julio de 2016. 
  17. Francesc Alted. «numexpr». Consultado el 8 de marzo de 2014. 
  18. «Numba». Consultado el 8 de marzo de 2014. 

Otras lecturas[editar]

Enlaces externos[editar]