Introducción a Numpy y Pandas

Intro a Numpy y Pandas

 

Python es el lenguaje más popular que encontrarás en el campo de la ciencia de datos por su simplicidad, la gran comunidad y la enorme disponibilidad de bibliotecas de código abierto. 

Si estás trabajando en un proyecto de ciencia de datos, los paquetes de Python te facilitarán la vida, ya que solo necesitas unas pocas líneas de código para realizar operaciones complicadas, como manipular los datos y aplicar un modelo de aprendizaje automático/aprendizaje profundo.

Cuando comiences tu viaje en la ciencia de datos, se recomienda comenzar aprendiendo dos de los paquetes de Python más útiles: NumPy y Pandas. En este artículo, presentamos estas dos bibliotecas. ¡Empecemos!

 

¿Qué es NumPy?

 

NumPy significa Numerical Python y se utiliza para realizar cálculos eficientes de matrices y matrices detrás de escena de los modelos de aprendizaje automático. El bloque de construcción de NumPy es el array, que es una estructura de datos muy similar a la lista, con la diferencia de que proporciona una gran cantidad de funciones matemáticas. En otras palabras, el array de NumPy es un objeto de matriz multidimensional. 

 

Crear arrays de NumPy

 

Podemos definir arrays de NumPy usando una lista o una lista de listas:

import numpy as np
l = [[1,2,3],[4,5,6],[7,8,9]]
numpy_array = np.array(l)
numpy_array

 

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

 

A diferencia de una lista de listas, podemos visualizar la matriz 3×3 con una sangría entre cada fila. Además, NumPy proporciona más de 40 funciones integradas para la creación de arrays. 

Para crear un array lleno de ceros, existe la función np.zeros , en la que solo necesitas especificar la forma que deseas:

zeros_array = np.zeros((3,4))
zeros_array

 

array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])

 

De la misma manera, podemos crear un array lleno de unos:

ones_array = np.ones((3,4))
ones_array

 

array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])

 

También existe la posibilidad de crear la matriz identidad, que es una matriz cuadrada con 1 en la diagonal principal y elementos fuera de la diagonal son 0:

identity_array = np.identity(3)
identity_array

 

array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

 

Además, NumPy proporciona diferentes funciones para crear arrays aleatorios. Para crear un array lleno de muestras aleatorias de una distribución uniforme en [0,1], solo necesitamos la función np.random.rand :

random_array = np.random.rand(3,4)
random_array

 

array([[0.84449279, 0.71146992, 0.48159787, 0.04927379],
       [0.03428534, 0.26851667, 0.65718662, 0.52284251],
       [0.1380207 , 0.91146148, 0.74171469, 0.57325424]])

 

De manera similar a la función anterior, podemos definir un array con valores aleatorios, pero esta vez se toman de una distribución normal estándar:

randn_array = np.random.randn(10)
randn_array

 

array([-0.68398432, -0.25466784,  0.27020797,  0.29632334, -0.20064897,
        0.7988508 ,  1.34759319, -0.41418478, -0.35223377, -0.10282884])

 

En caso de que estemos interesados en construir un array con enteros aleatorios que pertenezcan al intervalo [low,high), solo necesitamos la función np.random.randint:

randint_array = np.random.randint(1,20,20)
randint_array

 

array([14,  3,  1,  2, 17, 15,  5, 17, 18,  9,  4, 19, 14, 14,  1, 10, 17,
       19,  4,  6])

 

Indexación y Segmentación

 

Más allá de las funciones incorporadas para la creación de arrays, otro buen punto de NumPy es que es posible seleccionar elementos del array utilizando un conjunto de corchetes. Por ejemplo, podemos intentar tomar la primera fila de la matriz:

a1 = np.array([[1,2,3],[4,5,6]])
a1[0]

 

array([1, 2, 3])

 

Supongamos que queremos seleccionar el tercer elemento de la primera fila. En este caso, necesitamos especificar dos índices, el índice de la fila y el índice de la columna:

print(a1[0,2]) #3

 

Una alternativa es usar a1[0][2], pero se considera ineficiente porque primero crea el array que contiene la primera fila y luego selecciona el elemento de esa fila.

Además, podemos tomar segmentos de la matriz con la sintaxis inicio:fin:paso dentro de los corchetes, donde el índice de fin no está incluido. Por ejemplo, queremos nuevamente seleccionar la primera fila, pero solo tomamos los primeros dos elementos:

print(a1[0,0:2]) 

 

[1 2]

 

Si preferimos seleccionar todas las filas, pero queremos extraer el primer elemento de cada fila:

print(a1[:,0])

 

[1 4]

 

Además de la indexación de arrays de enteros, también existe la indexación de arrays booleanos para seleccionar los elementos de un array. Supongamos que solo queremos los elementos que cumplen la siguiente condición:

a1>5

 

array([[False, False, False],
       [False, False,  True]])

 

Si filtramos el array en base a esta condición, la salida mostrará solo los elementos True:

a1[a1>5]

 

array([6])

 

Manipulación de Arrays

 

Cuando se trabaja en proyectos de ciencia de datos, a menudo sucede que se necesita cambiar la forma de un array a una nueva forma sin cambiar los datos.

Por ejemplo, comenzamos con un array de dimensión 2X3. Si no estamos seguros de la forma de nuestro array, tenemos el atributo shape que puede ayudarnos:

a1 = np.array([[1,2,3],[4,5,6]])
print(a1)
print('Forma del Array: ',a1.shape)

 

[[1 2 3]
 [4 5 6]]
Forma del Array:  (2, 3)

 

Para cambiar la forma del array a la dimensión 3X2, simplemente podemos usar la función reshape:

a1 = a1.reshape(3,2)
print(a1)
print('Forma del arreglo: ',a1.shape)

 

[[1 2]
 [3 4]
 [5 6]]
Forma del arreglo:  (3, 2)

 

Otra situación común es convertir un arreglo multidimensional en un arreglo unidimensional. Esto es posible especificando -1 como forma:

a1 = a1.reshape(-1)
print(a1)
print('Forma del arreglo: ',a1.shape)

 

[1 2 3 4 5 6]
Forma del arreglo:  (6,)

 

También puede darse el caso de que necesites obtener un arreglo transpuesto:

a1 = np.array([[1,2,3,4,5,6]])
print('Antes de la forma del arreglo: ',a1.shape)
a1 = a1.T
print(a1)
print('Después de la forma del arreglo: ',a1.shape)

 

Antes de la forma del arreglo:  (1, 6)
[[1]
 [2]
 [3]
 [4]
 [5]
 [6]]
Después de la forma del arreglo:  (6, 1)

 

De la misma manera, puedes aplicar la misma transformación utilizando np.transpose(a1). 

 

Multiplicación de Arreglos

 

Si intentas construir algoritmos de aprendizaje automático desde cero, seguramente necesitarás calcular el producto matricial de dos arreglos. Esto es posible utilizando la función np.matmul cuando el arreglo tiene más de 1 dimensión:

a1 = np.array([[1,2,3],[4,5,6]])
a2 = np.array([[1,2],[4,5],[7,8]])
print('Forma del arreglo a1: ',a1.shape)
print('Forma del arreglo a2: ',a2.shape)
a3 = np.matmul(a1,a2) 
# a3 = a1 @ a2
print(a3)
print('Forma del arreglo a3: ',a3.shape)

 

Forma del arreglo a1:  (2, 3)
Forma del arreglo a2:  (3, 2)
[[30 36]
 [66 81]]
Forma del arreglo a3:  (2, 2)

 

@ puede ser una alternativa más corta a np.matmul. 

Si multiplicas una matriz por un escalar, np.dot es la mejor opción:

a1 = np.array([[1,2,3],[4,5,6]])
a3 = np.dot(a1,2)
# a3 = a1 * 2
print(a3)
print('Forma del arreglo a3: ',a3.shape)

 

[[ 2  4  6]
 [ 8 10 12]]
Forma del arreglo a3:  (2, 3)

 

En este caso, * es una alternativa más corta a np.dot. 

 

Funciones Matemáticas

 

NumPy proporciona una gran variedad de funciones matemáticas, como las funciones trigonométricas, funciones de redondeo, exponenciales, logaritmos, etc. Puedes encontrar la lista completa aquí. Vamos a mostrar las funciones más importantes que puedes aplicar a tus problemas.

La exponencial y el logaritmo natural son seguramente las transformaciones más populares y conocidas:

a1 = np.array([[1,2,3],[4,5,6]])
print(np.exp(a1))

 

[[  2.71828183   7.3890561   20.08553692]
 [ 54.59815003 148.4131591  403.42879349]]

 

a1 = np.array([[1,2,3],[4,5,6]])
print(np.log(a1))

 

[[0.         0.69314718 1.09861229]
 [1.38629436 1.60943791 1.79175947]]

 

Si queremos extraer el mínimo y el máximo en una sola línea de código, solo necesitamos llamar a las siguientes funciones:

a1 = np.array([[1,2,3],[4,5,6]])
print(np.min(a1),np.max(a1))  # 1 6

 

También podemos calcular la raíz cuadrada de cada elemento del array:

a1 = np.array([[1,2,3],[4,5,6]])
print(np.sqrt(a1))

 

[[1.         1.41421356 1.73205081]
 [2.         2.23606798 2.44948974]]

 

¿Qué es Pandas?

 

Pandas está construido sobre Numpy y es útil para manipular conjuntos de datos. Hay dos estructuras de datos principales: Series y Dataframe. Mientras que la Serie es una secuencia de valores, el dataframe es una tabla con filas y columnas. En otras palabras, la serie es una columna del dataframe.

 

Crear Series y Dataframe

 

Para construir la Serie, simplemente podemos pasar la lista de valores al método:

import pandas as pd
type_house = pd.Series(['Loft','Villa'])
type_house

 

0     Loft
1    Villa
dtype: object

 

Podemos crear un Dataframe pasando un diccionario de objetos, en el que las claves corresponden a los nombres de las columnas y los valores son las entradas de las columnas:

df = pd.DataFrame({'Price': [100000, 300000], 'date_construction': [1960, 2010]})
df.head()

 

 

Una vez que se crea el Dataframe, podemos verificar el tipo de cada columna:

type(df.Price),type(df.date_construction)

 

(pandas.core.series.Series, pandas.core.series.Series)

 

Debería quedar claro que las columnas son estructuras de datos del tipo Serie.

 

Funciones de resumen

 

A partir de ahora, mostraremos las potencialidades de Pandas utilizando el conjunto de datos de uso compartido de bicicletas, disponible en Kaggle. Podemos importar el archivo CSV de la siguiente manera:

df = pd.read_csv('/kaggle/input/bike-sharing-demand/train.csv')
df.head()

 

 

Pandas no solo permite leer archivos CSV, sino también archivos de Excel, JSON, Parquet y otros tipos de archivos. Puedes encontrar la lista completa aquí.

A partir de la salida, podemos visualizar las primeras cinco filas del dataframe. Si queremos mostrar las últimas cuatro filas del conjunto de datos, usamos el método tail():

df.tail(4)

 

 

Pocas filas no son suficientes para tener una buena idea de los datos que tenemos. Una buena manera de comenzar el análisis es mirando la forma del conjunto de datos:

df.shape                    #(10886, 12)

 

Tenemos 10886 filas y 12 columnas. ¿Quieres ver los nombres de las columnas? Es muy intuitivo hacerlo:

df.columns

 

 

Hay un método que permite visualizar toda esta información en una única salida:

df.info()

 

 

Si queremos mostrar las estadísticas de cada columna, podemos usar el método describe:

df.describe()

 

 

También es importante extraer información de los campos categóricos. Podemos encontrar los valores únicos y el número de valores únicos de la columna season:

df.season.unique(), df.season.nunique()

 

Resultado:

(array([1, 2, 3, 4]), 4)

 

Podemos ver que los valores son 1, 2, 3, 4. Entonces, hay cuatro posibles valores. Esta verificación es crucial para comprender las variables categóricas y prevenir posibles ruidos contenidos en la columna.

Para mostrar la frecuencia de cada nivel, podemos usar el método value_counts():

df.season.value_counts()

 

 

El último paso debería ser la inspección de los valores faltantes en cada columna:

df.isnull().sum()

 

 

Afortunadamente, no tenemos ningún valor faltante en ninguno de estos campos.

 

Indexación y Segmentación

 

Al igual que en Numpy, hay una selección basada en índices para seleccionar datos de la estructura de datos. Hay dos métodos principales para tomar entradas del dataframe:

  • iloc selecciona los elementos basados en la posición entera
  • loc toma los elementos basados en etiquetas o en una matriz booleana.

Para seleccionar la primera fila, iloc es la mejor opción:

df.iloc[0]

 

 

Si en cambio queremos seleccionar todas las filas y solo la segunda columna, podemos hacer lo siguiente:

df.iloc[:,1]

 

 

También es posible seleccionar varias columnas al mismo tiempo:

df.iloc[0:3,[0,1,2,5]]

 

 

Se vuelve más complejo seleccionar las columnas basadas en los índices. Sería mejor especificar los nombres de las columnas. Esto es posible usando loc:

df.loc[0:3,['datetime','season','holiday','temp']]

 

 

De manera similar a Numpy, es posible filtrar el dataframe basado en condiciones. Por ejemplo, si queremos devolver todas las filas donde el clima es igual a 1:

df[df.weather==1]

 

 

En caso de que queramos devolver una salida con columnas específicas, podemos usar loc:

df.loc[df.weather==1,['season','holiday']]

 

 

Crear nuevas variables

 

La creación de nuevas variables tiene un gran impacto en la extracción de más información de los datos y en la mejora de la interpretación. Podemos crear una nueva variable categórica basada en los valores de workingday:

df['workingday_c'] = df['workingday'].apply(lambda x: 'trabajo' if x==1 else 'descanso')
df[['workingday','workingday_c']].head()

 

 

Si hay más de una condición, es mejor mapear los valores utilizando un diccionario y el método map:

diz_season = {1:'invierno',2:'primavera',3:'verano',4:'otoño'}
df['season_c'] = df['season'].map(lambda x: diz_season[x])
df[['season','season_c']].head()

 

 

Agrupación y ordenamiento

 

Puede suceder que desee agrupar los datos según columna(s) categórica(s). Esto es posible utilizando groupby:

df.groupby('season_c').agg({'count':['mediana','máximo']})

 

 

Para cada nivel de la estación, podemos observar la mediana y el máximo conteo de bicicletas alquiladas. Esta salida puede ser confusa sin ordenarla en función de una columna. Podemos hacerlo utilizando el método sort_values():

df.groupby('season_c').agg({'count':['mediana','máximo']}).reset_index().sort_values(by=('count', 'mediana'),ascending=False)

 

 

Ahora, la salida tiene más sentido. Podemos deducir que el mayor número de bicicletas alquiladas es en verano, mientras que el invierno no es un buen mes para alquilar bicicletas.

 

Pensamientos finales

 

¡Eso es todo! Espero que hayas encontrado útil esta guía para aprender los conceptos básicos de NumPy y Pandas. A menudo se estudian por separado, pero puede ser esclarecedor entender primero NumPy y luego Pandas, que se construye sobre NumPy.

Seguramente hay métodos que no he cubierto en el tutorial, pero el objetivo era cubrir los métodos más importantes y populares de estas dos bibliotecas. El código se puede encontrar en Kaggle. ¡Gracias por leer! ¡Que tengas un buen día!     Eugenia Anello es actualmente investigadora en el Departamento de Ingeniería de la Información de la Universidad de Padua, Italia. Su proyecto de investigación se centra en el Aprendizaje Continuo combinado con la Detección de Anomalías.

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

Esta investigación de IA revela el LSS Transformer Un enfoque revolucionario de IA para el entrenamiento eficiente de secuencias largas en los Transformers.

Una nueva investigación de IA ha presentado el Long Short-Sequence Transformer (LSS Transformer), un método eficiente...

Inteligencia Artificial

Dentro del acalorado centro del pesimismo de la IA

Anthropic, una start-up de inteligencia artificial centrada en la seguridad, está tratando de competir con ChatGPT mi...

Inteligencia Artificial

Análisis y optimización del rendimiento del modelo PyTorch - Parte 3

Esta es la tercera parte de una serie de publicaciones sobre el tema de analizar y optimizar modelos de PyTorch utili...

Inteligencia Artificial

Más desarrolladores están utilizando el lenguaje Rust

La encuesta Estado de Rust 2022 publicada a principios de este mes encontró a más desarrolladores utilizando el lengu...

Investigación

Usando reflexiones para ver el mundo desde nuevos puntos de vista.

Un nuevo sistema de visión por computadora convierte cualquier objeto brillante en una especie de cámara, lo que perm...

Inteligencia Artificial

Una nueva investigación de IA de Italia presenta un modelo generativo basado en difusión capaz tanto de la síntesis musical como de la separación de fuentes

Los seres humanos son capaces de procesar varias fuentes de sonido al mismo tiempo, tanto en términos de composición ...