[1, 2, 3]
Estructuras de Datos
Los datos son la base de la ciencia, son la materia prima con la que trabajamos. Dada su importancia es necesario contar con herramientas que nos permitan manipularlos de manera eficiente. En este sentido, las estructuras de datos son una herramienta fundamental en la programación. Se definen como formas de organizar y almacenar datos en la memoria de un computador, de tal manera que se puedan acceder y modificar de manera eficiente.
En esta lección veremos algunas de las estructuras de datos más comunes en Python, como las listas, tuplas, conjuntos, diccionarios, arreglos de NumPy y DataFrames
de Pandas, así como las propiedades y métodos que las caracterizan.
Listas
Las listas son una de las estructuras de datos más comunes en Python. Se definen como una colección ordenada de elementos, que pueden ser de cualquier tipo. Para definir una lista se utilizan corchetes []
y los elementos se separan por comas ,
.
Las listas se suelen utilizar para almacenar colecciones de elementos relacionados, como los números de una serie, los nombres de los estudiantes de una clase, las coordenadas de un punto, etc. En general usamos listas cuando necesitamos almacenar una colección de elementos que pueden ser modificados durante la ejecución del programa.
Las listas son mutables, lo que significa que se pueden modificar después de haber sido creadas. Por ejemplo, se pueden agregar elementos a una lista con el método append()
. Los métodos son funciones que se pueden aplicar a un objeto, en este caso a una lista y se sigue la sintaxis objeto.metodo()
. Nuestro objeto es la lista y el método es append()
.
Iniciemos una lista vacía y agreguemos elementos a ella.
Otro método útil es extend()
, que permite agregar varios elementos a la vez.
Las listas pueden contener elementos de diferentes tipos, incluso otras listas.
[1, 2, 3, 4, 5, 6, [7, 8, 9]]
[1, 2, 3, 4, 5, 6, [7, 8, 9], 'hola']
Indexación
Para acceder a elementos de una lista se utiliza la indexación. Los índices en Python comienzan en 0, por lo que el primer elemento de una lista tiene índice 0, el segundo índice 1 y así sucesivamente. Para acceder a un elemento de una lista se utiliza la sintaxis nombredelista[indice]
.
Slicing
El slicing es una técnica que permite acceder a subconjuntos de elementos de una lista. Se utiliza la sintaxis nombredelista[inicio:fin]
, donde inicio
es el índice del primer elemento que se quiere incluir y fin
es el índice del primer elemento que no se quiere incluir.
Si no se especifica el índice de inicio, se asume que es 0. Si no se especifica el índice de fin, se asume que es el último elemento de la lista.
Modificación
Para modificar un elemento de una lista se utiliza la indexación y la asignación.
Eliminación
Para eliminar un elemento de una lista se utiliza el método remove()
y se especifica el elemento del elemento que se quiere eliminar.
Si queremos eliminar el último elemento de una lista se puede utilizar el método pop()
.
Resumen
Las listas tienen un gran número de métodos que permiten realizar operaciones sobre ellas. Un resumen de los métodos más comunes es el siguiente:
append()
: Agrega un elemento al final de la lista.extend()
: Agrega varios elementos al final de la lista.insert()
: Agrega un elemento en una posición específica.remove()
: Elimina un elemento de la lista.pop()
: Elimina un elemento de la lista y lo devuelve.index()
: Devuelve el índice de un elemento en la lista.count()
: Cuenta el número de veces que un elemento aparece en la lista.sort()
: Ordena los elementos de la lista en orden ascendente.reverse()
: Invierte el orden de los elementos de la lista.copy()
: Crea una copia de la lista.
Vale la pena hacer enfásis en que no es necesario aprenderse todos los métodos de memoria, sino que es más importante entender para qué y cómo se pueden utilizar las listas, los métodos se pueden consultar en la documentación de Python, buscando en Google o preguntandole a ChatGPT.
Tuplas
Las tuplas son una estructura de datos similar a las listas, pero con la diferencia de que son inmutables, es decir, una vez creadas no se pueden modificar. Se definen utilizando paréntesis ()
y los elementos se separan por comas ,
.
Las tuplas se utilizan cuando se necesita almacenar una colección de elementos que no van a cambiar durante la ejecución del programa como el número de ensayos de un experimento, las coordenadas de un punto, etc.
Las tuplas soportan indexación, slicing y la función len()
para obtener la longitud de la tupla.
1
2
(1, 2, 3)
5
Las tuplas también pueden contener elementos de diferentes tipos y otras tuplas.
Conjuntos
Los conjuntos son una estructura de datos que almacena elementos únicos, es decir, no se pueden repetir. Se definen utilizando llaves {}
y los elementos se separan por comas ,
.
Funcionan igual que los conjuntos matemáticos, por lo que se pueden realizar operaciones como unión, intersección, diferencia, etc. Los conjuntos no soportan indexación ni slicing, ya que no tienen un orden definido.
Código
conjunto1 = {1, 2, 3, 4, 5}
conjunto2 = {4, 5, 6, 7, 8}
# Unión de conjuntos
print(conjunto1.union(conjunto2))
# Intersección de conjuntos
print(conjunto1.intersection(conjunto2))
# Diferencia de conjuntos
print(conjunto1.difference(conjunto2))
# Diferencia simétrica de conjuntos
print(conjunto1.symmetric_difference(conjunto2))
{1, 2, 3, 4, 5, 6, 7, 8}
{4, 5}
{1, 2, 3}
{1, 2, 3, 6, 7, 8}
Se pueden agregar elementos a un conjunto con el método add()
y eliminar elementos con el método remove()
.
Diccionarios
Los diccionarios son una estructura de datos que almacena pares de clave-valor, es decir, cada elemento del diccionario tiene una clave que lo identifica y un valor asociado. Se definen utilizando llaves {}
, los pares clave-valor se separan por comas ,
y la clave y el valor se separan por dos puntos :
.
Para acceder a un valor de un diccionario se utiliza la clave correspondiente.
Código
Juan
25
Bogotá
Este tipo de estructura es muy útil para almacenar información estructurada, como los datos de una persona, los resultados de un experimento, etc. Los diccionarios son mutables, por lo que se pueden modificar, agregar y eliminar elementos.
Código
{'nombre': 'Juan', 'edad': 30, 'ciudad': 'Bogotá'}
{'nombre': 'Juan', 'edad': 30, 'ciudad': 'Bogotá', 'telefono': '123456789'}
{'nombre': 'Juan', 'edad': 30, 'ciudad': 'Bogotá'}
Los diccionarios tienen varios métodos útiles, como keys()
, values()
y items()
que permiten obtener las claves, los valores y los pares clave-valor del diccionario, respectivamente.
dict_keys(['nombre', 'edad', 'ciudad'])
dict_values(['Juan', 30, 'Bogotá'])
dict_items([('nombre', 'Juan'), ('edad', 30), ('ciudad', 'Bogotá')])
Es importante tener en cuenta que las claves de un diccionario deben ser únicas, es decir, no puede haber dos claves iguales en un diccionario. Si se intenta agregar una clave que ya existe, se reemplazará el valor asociado a esa clave.
Otra característica importante de los diccionarios es que no tienen un orden definido, es decir, los elementos no se almacenan en el orden en que se agregaron, pero son altamente eficientes para buscar y acceder a elementos por su clave, formalmente se dice que tienen una complejidad de tiempo de acceso de \(O(1)\) una caractertica común en las estructuras de datos de tipo hash.
Ejericios
Crea una lista con los números del 1 al 10 y calcula la suma de los elementos. Pista: utiliza la función
sum()
de Python.Crea una tupla con los nombres de los días de la semana y accede al tercer día. Intenta modificar el tercer día y observa qué sucede.
Crea una variable con la letra de una canción que te guste, separa las palabras en una lista, guarda esa lista en una variable y accede a la primera y última palabra. Pista: utiliza el método
split()
de Python.Convierte la lista de palabras en un conjunto y observa qué sucede. ¿Qué diferencias encuentras entre la lista y el conjunto? Intenta agregar una palabra al conjunto y observa qué sucede. Pista: utiliza la función
set()
de Python y el métodoadd()
de los conjuntos.Crea una función para contar palabras en un texto, cuenta las palabras distintas en la letra de una canción que te guste y almacenalas en un diccionario con la palabra como clave y el número de veces que aparece como valor. Pista: utiliza el método
split()
para separar las palabras
Arreglos de NumPy
NumPy es una librería de Python que permite trabajar con arreglos multidimensionales de manera eficiente. Los arreglos de NumPy son similares a las listas de Python, pero con la diferencia de que todos los elementos de un arreglo de NumPy deben ser del mismo tipo. Se definen utilizando la función array()
de NumPy.
Este tipo de estructuras son ampliamente utilizadas en la ciencia de datos, ya que permiten realizar operaciones matemáticas sobre los datos de manera eficiente. Los arreglos de NumPy soportan indexación, slicing y operaciones matemáticas como suma, resta, multiplicación, operacioens de matrices, etc.
Código
import numpy as np
arreglo = np.array([1, 2, 3, 4, 5]) # Crear un arreglo de NumPy
print(arreglo) # Imprimir el arreglo
print(arreglo[0]) # Acceder al primer elemento
print(arreglo[0:3]) # Acceder a los primeros tres elementos
print(arreglo + 10) # Sumar 10 a cada elemento
print(arreglo * 2) # Multiplicar cada elemento por 2
[1 2 3 4 5]
1
[1 2 3]
[11 12 13 14 15]
[ 2 4 6 8 10]
Las operaicones matemáticas en NumPy se realizan elemento a elemento, es decir, se aplican a cada elemento del arreglo por separado. Esto es muy útil para realizar operaciones matemáticas sobre grandes cantidades de datos de manera eficiente.
Podemos crear arreglos de NumPy multidimensionales, es decir, arreglos que contienen otros arreglos. Por ejemplo, un arreglo de dos dimensiones es similar a una matriz.
[[1 2 3]
[4 5 6]
[7 8 9]]
Para acceder a elementos de una matriz se utiliza la indexación con dos índices, uno para la fila y otro para la columna.
DataFrames de Pandas
Pandas es una librería de Python que permite trabajar con datos estructurados de manera eficiente. Una de las estructuras de datos más importantes de Pandas es el DataFrame
, que es una tabla de datos bidimensional con filas y columnas. Se puede pensar en un DataFrame
como una hoja de cálculo de Excel o una tabla de una base de datos.
Para crear un DataFrame
se utiliza la función DataFrame()
de Pandas y se le pasa un diccionario con los datos.
Código
nombre edad ciudad
0 Juan 25 Bogotá
1 María 30 Medellín
2 Pedro 35 Cali
3 Ana 40 Barranquilla
Pandas incluye una serie de funciones y métodos para trabajar con DataFrames
, como head()
, tail()
, info()
, describe()
, etc. Exploraremos en profundidad estas funciones en una lección posterior.
Slicing en DataFrames
Por ahora veamos cómo acceder a elementos de un DataFrame
. Podemos acceder a las primeras y últimas filas de un DataFrame
utilizando los métodos head()
y tail()
, respectivamente
Código
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
2 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
3 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
4 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
145 | 6.7 | 3.0 | 5.2 | 2.3 | virginica |
146 | 6.3 | 2.5 | 5.0 | 1.9 | virginica |
147 | 6.5 | 3.0 | 5.2 | 2.0 | virginica |
148 | 6.2 | 3.4 | 5.4 | 2.3 | virginica |
149 | 5.9 | 3.0 | 5.1 | 1.8 | virginica |
Podemos acceder a las columnas de un DataFrame
utilizando la indexación con corchetes []
y el nombre de la columna entre comillas simples o dobles.
0 5.1
1 4.9
2 4.7
3 4.6
4 5.0
...
145 6.7
146 6.3
147 6.5
148 6.2
149 5.9
Name: sepal_length, Length: 150, dtype: float64
Otra manera de acceder a una columna es utilizando la notación de punto .
y el nombre de la columna, pero esta forma no es muy usada dado que complica el acceso a columnas con nombres que contienen espacios o caracteres especiales.
0 5.1
1 4.9
2 4.7
3 4.6
4 5.0
...
145 6.7
146 6.3
147 6.5
148 6.2
149 5.9
Name: sepal_length, Length: 150, dtype: float64
También podemos acceder a filas y columnas utilizando la función loc[]
y los nombres de las filas y columnas.
Código
0 5.1
1 4.9
2 4.7
3 4.6
4 5.0
...
145 6.7
146 6.3
147 6.5
148 6.2
149 5.9
Name: sepal_length, Length: 150, dtype: float64
Si queremos seleccionar varias columnas podemos pasar una lista con los nombres de las columnas.
Código
sepal_length | sepal_width | |
---|---|---|
0 | 5.1 | 3.5 |
1 | 4.9 | 3.0 |
2 | 4.7 | 3.2 |
3 | 4.6 | 3.1 |
4 | 5.0 | 3.6 |
... | ... | ... |
145 | 6.7 | 3.0 |
146 | 6.3 | 2.5 |
147 | 6.5 | 3.0 |
148 | 6.2 | 3.4 |
149 | 5.9 | 3.0 |
150 rows × 2 columns
Si queremos seleccionar las filas 5, 14, 23 y las columnas ‘sepal_length’ y ‘sepal_width’ podemos hacerlo de la siguiente manera.
Modificación de DataFrames
Podemos agregar una nueva columna a un DataFrame
utilizando la notación de corchetes []
y el nombre de la nueva columna y asignándole una lista con los valores de la columna.
Creemos una nueva columna que contenga la suma de las columnas ‘sepal_length’ y ‘sepal_width’.
sepal_length | sepal_width | petal_length | petal_width | species | sepal_sum | |
---|---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | setosa | 8.6 |
1 | 4.9 | 3.0 | 1.4 | 0.2 | setosa | 7.9 |
2 | 4.7 | 3.2 | 1.3 | 0.2 | setosa | 7.9 |
3 | 4.6 | 3.1 | 1.5 | 0.2 | setosa | 7.7 |
4 | 5.0 | 3.6 | 1.4 | 0.2 | setosa | 8.6 |
Para eliminar una columna de un DataFrame
se utiliza el método drop()
y se pasa el nombre de la columna y el eje en el que se quiere eliminar, los ejes son 0 para filas y 1 para columnas.
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
2 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
3 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
4 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
El parámetro inplace=True
indica que la operación se realice sobre el DataFrame
original, si se omite se crea una copia del DataFrame
con la columna eliminada, pero si esta copia no se asigna a una variable se perderá.
Si queremos modificar un valor de un DataFrame
se localiza el elemento con loc[]
y se asigna el nuevo valor.
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
2 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
3 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
4 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
0 | 10.0 | 3.5 | 1.4 | 0.2 | setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
2 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
3 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
4 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
Conclusiones
En esta lección hemos visto algunas de las estructuras de datos más comunes en Python, como las listas, tuplas, conjuntos, diccionarios, arreglos de NumPy y DataFrames
de Pandas. Cada una de estas estructuras tiene sus propias características y métodos que permiten realizar operaciones sobre los datos de manera eficiente. Cada estructura de datos es adecuada para diferentes tipos de problemas, por lo que es importante conocerlas y saber cuándo utilizar cada una. En las siguientes lecciones veremos cómo trabajar con estas estructuras de datos en la práctica y cómo realizar operaciones más avanzadas sobre los datos.