Autores: Manuel Jesús Gómez Moratilla, José Antonio Ruipérez Valiente y Mariano Albaladejo González
Notebooks¶https://colab.research.google.com
Antes de comenzar con la práctica, vamos a detenernos a analizar el entorno de ejecución en el que nos encontramos y el funcionamiento de los propios notebooks. Como podemos comprobar, el notebook o cuaderno está divido en distintas celdas, cada una de las cuales puede contener o bien texto, o bien código.
Si se está usando Google Colab para la ejecución del cuaderno, vemos que en la parte superior izquierda tenemos dos opciones para añadir celdas (una para celdas de código y otra para celdas de texto). Podéis interactuar con estos botones y ver el resultado de añadir los distintos tipos de celdas.
# Esta es una celda de código
En las celdas de código aparece un icono a la izquierda con un botón para su ejecución. Si lo pulsamos, se ejecutará el código asociado a la celda correspondiente.
print("Hola mundo")
Hola mundo
Entorno de ejecución -> Reiniciar sesión: Reinicia el notebook.Archivo -> Guardar / Ctrl + S: Guarda el estado del notebook. Aunque el notebook tiene autoguardado, este no es de fiar :)Entorno de ejecución -> Desconectarse y eliminar entorno: Cierra el notebook y desconecta la sesión.Archivo -> Cambiar nombre / Click sobre el nombre del notebook: Renombra el notebook.Insertar -> Insertar celda de código: Añade una celda vacía de código a continuación.Insertar -> Insertar celda de texto: Añade una celda vacía de texto a continuación.Editar -> Eliminar celdas seleccionadas / Keyboard(Ctrl + M D): Elimina la(s) celda(s) seleccionada(s).No existe un estándar definido para Markdown. Existen diversas implementaciones de Markdown en distintas plataformas que varían ligeramente:
Markdown es el lenguaje utilizado normalmente para escribir celdas de texto
Doble clickCtrl + Enter / Shift + Enter| Estilos en Markdown | Resultado |
|---|---|
**Texto en negrita** |
Texto en negrita |
*Texto en itálica* o _Texto en itálica_ |
Texto en itálica |
~~Texto tachado~~ |
|
`Texto monoespaciado` |
Texto monoespaciado |
[Link a GitHub](www.github.com) |
Link a GitHub |
 |
![]() |
> Un nivel de indentación
Indentación 1
>> Dos niveles de indentación
Indentación 2
>>> Tres niveles de indentación
Indentación 3
* Elemento 1
* Elemento 2
* Elemento 3
Y anidar listas:
Cabecera primera columna | Cabecera segunda columna | ... | Cabecera N columna
---|---|---|---
Fila 1 columna 1 | Fila 1 columna 2 | ... | Fila 1 columna N
Fila 2 columna 1 | Fila 2 columna 2 | ... | Fila 2 columna N
... | ... | ... | ...
Fila M columna 1 | Fila M columna 2 | ... | Fila M columna N
| Cabecera primera columna | Cabecera segunda columna | ... | Cabecera columna N |
|---|---|---|---|
| Fila 1 columna 1 | Fila 1 columna 2 | ... | Fila 1 columna N |
| Fila 2 columna 1 | Fila 2 columna 2 | ... | Fila 2 columna N |
| ... | ... | ... | ... |
| Fila M columna 1 | Fila M columna 2 | ... | Fila M columna N |
(pip debería haberse instalado automáticamente con Python en el sistema)
pip --version! pip --version
pip 23.1.2 from /usr/local/lib/python3.10/dist-packages/pip (python 3.10)
Para descargar cualquier paquete de software:
pip install [options] <package>
El entorno Jupyter Notebook no incluye todas las librerías posibles.
pip install para descargar las dependencias que hagan falta más adelante.En los notebook de Colab lo hacemos de la siguiente manera:
! pip install numpy
Requirement already satisfied: numpy in /usr/local/lib/python3.10/dist-packages (1.23.5)
pip --helppip [command] --helppip uninstall: Elimina un paquete.pip list: Muestra todos los paquetes junto con su versión actual.pip install --upgrade: Actualiza una librería.En este primera práctica vamos a hacer un repaso general del lenguaje de programación Python.
La práctica constará de una sola sesión (entregable): repasaremos las principales funcionalidades del lenguaje de programación Python, y ampliaremos esto viendo las primeras funcionalidades de Pandas. Además se propondrán una serie de ejercicios para ir familiarizándonos tanto con el lenguaje como con la librería Pandas.
Las reglas básicas para escribir expresiones simples en Python son:
# indica que el resto de la línea es un comentario1+2
+3 # continuación ilegal de la suma
(1+2
+ 3) # OK, incluso con espacios
Python¶Algunos ejemplos de tipos de datos básicos son:
Int: numero entero, por ejemplo, 1, 2, 3, 4.String: una cadena de texto, como “Programming” o “Python”.Float: un número decimal, como 10.2, 23.5 o 2.0.Boolean: valor booleano. Contiene dos valores: False (Falso) y True (Verdadero). Estos valores también se suelen representar mediante el 0 y el 1, respectivamente.Veamos ejemplos funcionales usando estos tipos de datos:
#Asignamos a la variable "a" el numero 12.5
#Asignamos a la variable "b" el numero 13.5
#Asignamos a la variable "c" el numero 22.2
a = 12.5
b = 12.5
c = 22.2
# Operaciones basicas
print(a + b)
print(a - b)
25.0 0.0
# Comparaciones de mayor y menor entre variables
a > b
False
a >= b
True
# ¿Son iguales?
c == a
False
# Cadenas de texto - Strings
cadena1 = 'Mi primera cadena de texto'
cadena2 = "Mi primera cadena de Texto"
cadena1 == cadena2
False
# Para comprobar el tipo de una variable
type("hola")
str
type(c)
float
Representan una condición que debe cumplirse para que el código a continuación se ejecute.
if (cadena1 == cadena2):
print("Son iguales")
else:
print("No son iguales")
No son iguales
Respuesta 1:
# Resuelve aquí
if:
else:
Ahora vamos a ver algunas funcionalidades básicas de las que Python pone a nuestro alcance para el manejo de strings:
string1 = "esto es una cadena de texto"
string2 = "esto es otra cadena de texto"
# Subcadenas - puesto que cada string puede ser visto como una lista de caracteres individuales, podemos dividir
# nuestra cadena de forma sencilla tratándola como una lista de elementos:
# Accedemos a las posiciones 0-3
string1[0:3]
'est'
string2[0:16]
'esto es otra cad'
# Podemos transformar la cadena a mayúsculas:
string1.upper()
'ESTO ES UNA CADENA DE TEXTO'
# Comprobar si empieza por otra cadena
string2.startswith('eto')
False
string2.startswith('esto')
True
# Comprobar si una cadena está contenida en otra
print("otra" in string1)
print("otra" in string2)
False True
Respuesta 2:
# Resuelve aquí
if :
else:
# Partir una cadena con respecto a un patrón
string1 = "esto es una cadena de texto"
string1.split(" ")
['esto', 'es', 'una', 'cadena', 'de', 'texto']
# Reemplazar el contenido de una cadena
string2 = string1.replace("una cadena de texto", "un string")
string2
'esto es un string'
Las estructuras de datos en Python se pueden entender como un tipo de dato compuesto, ya que en una sola variable podemos almacenar una estructura completa con información, cada una con distintas características y funcionalidades. En Python existen distintas estructuras de datos, como las listas, matrices o diccionarios.
Empecemos viendo las listas:
# Crear una lista vacía
lista1 = list()
lista1 = []
lista1
[]
lista1.append(a)
lista1
[12.5]
#Crear una lista con elementos predefinidos
lista2 = [b, c]
lista2
[12.5, 22.2]
lista1.extend(lista2)
lista1
[12.5, 12.5, 22.2]
# Comprobar la longitud de una lista
len(lista1)
3
# Una lista puede tener distintos tipos de datos
lista1.append("cadena")
lista1.append(True)
lista1
[12.5, 12.5, 22.2, 'cadena', True]
# Eliminar elementos de una lista
lista1.remove('cadena')
lista1
[12.5, 12.5, 22.2, True]
lista1.remove(12.5)
lista1
[12.5, 22.2, True]
# También podemos vaciar la lista con clear:
lista1.clear()
lista1
[]
Conjuntos:¶Un conjunto, por definición es "una colección no ordenada de objetos únicos". Python permite el uso de conjuntos de manera sencilla, y su funcionamiento es similar al de las listas, con ciertas diferencias:
# Conjunto vacío
conjunto = set()
# Añadimos elementos con add
conjunto.add(1)
conjunto.add(2)
conjunto.add("hola")
conjunto.add(1)
conjunto
{1, 2, 'hola'}
Como vemos, si intentamos introducir un elemento que ya existe en el conjunto, la operación no tiene efecto.
# Para eliminar un elemento:
conjunto.discard(1)
conjunto
{2, 'hola'}
Diccionarios:¶Los diccionarios son estructuras que contienen asociaciones clave- valor. Es decir, para cada clave que definamos en el diccionario, habrá asociado un valor. Es un tipo de datos muy potente, ya que este valor asociado puede ser cualquier tipo de dato, un entero, una cadena de texto o incluso otro diccionario.
# Para definir un diccionario vacío
diccionario = dict()
diccionario = {}
diccionario
{}
# Para definir un diccionario con pares existentes:
diccionario = {'clave1': 'valor1', 'clave2': 12}
diccionario
{'clave1': 'valor1', 'clave2': 12}
# Para añadir una nueva entrada al diccionario o modificar una ya existente:
diccionario['clave3'] = 'valor3'
diccionario['clave2'] = 'valor2'
diccionario
{'clave1': 'valor1', 'clave2': 'valor2', 'clave3': 'valor3'}
# Para acceder al valor de una clave en concreto:
diccionario['clave2']
'valor2'
# También podemos obtener una estructura iterable con el conjunto de claves
print(diccionario.keys())
# y de valores
print(diccionario.values())
dict_keys(['clave1', 'clave2', 'clave3']) dict_values(['valor1', 'valor2', 'valor3'])
# Y podemos crear una lista y/o conjunto a partir de estas estructuras
list(diccionario.keys()) # y lo mismo con set()
['clave1', 'clave2', 'clave3']
# Por último, podemos eliminar elementos de la siguiente manera:
diccionario.pop('clave2')
'valor2'
diccionario
{'clave1': 'valor1', 'clave3': 'valor3'}
Respuesta 3:
# Resuelve aquí:
# Recorrer una lista
lista1 = [12.5, 12.5, 22.2, 'cadena']
for elemento in lista1:
print(type(elemento))
<class 'float'> <class 'float'> <class 'float'> <class 'str'>
El bucle iterativo for puede utilizarse en cualquier estructura iterable de Python, como Series o matrices.
Respuesta 4:
# Resuelve aquí
for cadena in :
print()
while¶El bucle while se utiliza en Python para ejecutar un fragmento de código mientras que una determinada condición sea cierta. Por ejemplo, vamos a imprimir por pantalla el valor de una variable i definida basado en el valor de dicha variable:
i = 10
while (i > 0) :
print("El valor de la variable es: " + str(i))
i -= 1
El valor de la variable es: 10 El valor de la variable es: 9 El valor de la variable es: 8 El valor de la variable es: 7 El valor de la variable es: 6 El valor de la variable es: 5 El valor de la variable es: 4 El valor de la variable es: 3 El valor de la variable es: 2 El valor de la variable es: 1
Vemos en el código que en cada pasada del bucle, restamos 1 a la variable i. Como esta había sido definida con valor 10, y la condición para continuar es que i sea mayor que 0, el bucle se ejecutará 10 veces hasta que la condición deje de cumplirse.
También podemos parar el bucle con break aunque la condición sea cierta:
i = 10
while (i > 0) :
print("El valor de la variable es: " + str(i))
i -= 1
if (i == 5):
break
El valor de la variable es: 10 El valor de la variable es: 9 El valor de la variable es: 8 El valor de la variable es: 7 El valor de la variable es: 6
Por último, el bucle while permite el uso de la sentencia continue para parar la iteración actual, pero sin parar el bucle:
i = 10
while (i > 0) :
if (i == 5):
break
i -= 1
if (i == 7):
continue
print("El valor de la variable es: " + str(i))
El valor de la variable es: 9 El valor de la variable es: 8 El valor de la variable es: 6 El valor de la variable es: 5
for):¶Respuesta 5:
# Resuelve aquí
Python¶En Python, un módulo es un archivo (normalmente en extensión .py o .pyd) que contiene definiciones de variables, funciones, clases, excepciones, y cualquier otro tipo de objeto definible en el lenguaje. Los módulos puede importarse de manera que estas funciones, clases... sean accesibles desde otro módulo o script de Python.
Para importar cualquier módulo o paquete, utilizaremos las palabras reservadas from e import:
Para importar un módulo completo utilizaremos import modulo.
Para seleccionar las funciones, variables... en concreto que queremos importar, utilizaremos from modulo import funcion
# Para cargar el módulo de Numpy
import numpy
Sin embargo, en muchas ocasiones el nombre del módulo no será intuitivo de usar, o simplemente nos gustaría llamarlo de otra manera. Para ello existen los alias, que nos permiten cambiar el nombre del módulo o paquete para su posterior uso en nuestro código:
import numpy as np
A partir de ahora, podremos usar el alias np para llamar a cualquier función del módulo Numpy
En esta segunda sesión (la segunda de la práctica 1) vamos a hacer una introducción a la exploración de datos y el pre-procesamiento de estos utilizando Pandas en Python. Pandas es una biblioteca de código abierto que proporciona estructuras de datos de alto rendimiento y herramientas de análisis de datos para el lenguaje de programación Python.
Durante esta sesión, nos centraremos en utilizar las funcionalidades proporcionadas por Pandas para preparar nuestros datos para futuros análisis. Esto incluirá la manipulación de datos, el filtrado de datos y otras operaciones útiles que nos permitirán comprender mejor nuestro conjunto de datos y extraer información relevante de él.
Para comenzar, vamos a leer los datos en formato CSV. CSV son las siglas de Comma-Separated Values, valores separados por coma, y es una manera muy común de almacenar datos. Además, otros delimitadores pueden ser usados en lugar de la coma para separar los valores, por ejemplo, \t o ;.
La primera línea del archivo normalmente incluye los nombres de las distintas columnas o campos del fichero. Veamos un ejemplo de las tres primeras líneas del fichero CSV que vamos a usar:
First Name,Gender,Start Date,Last Login Time,Salary,Bonus %,Senior Management,Team
Douglas,Male,8/6/1993,12:42 PM,97308,6.945,true,Marketing
Maria,Female,4/23/1993,11:17 AM,130590,11.858,false,Finance
Como podemos comprobar, cada campo está separado por comas, teniendo en la primera línea los nombres que definirán las columnas de nuestro conjunto de datos. En nuestro caso, utilizaremos la función de Pandas read_csv() para leer el fichero directamente del sistema. Está función transformará el fichero directamente a un DataFrame. Pero antes de leer dicho fichero, ¿qué es un DataFrame?
Un DataFrame es una estructura de datos con dos dimensiones (filas y columnas) en la cual se puede guardar datos de distintos tipos, como cadenas de texto, enteros, o incluso estructuras complejas como listas o diccionarios. Es similar a una hoja de cálculo de Excel o a un data.frame de R. Un DataFrame siempre tiene un índice (con inicio en 0). El índice refiere a la posición de un elemento en la estructura de datos.
Ahora sí, procedemos a leer los datos. La función read_csv() tiene múltiples parámetros para leer todo tipo de ficheros, como el parámetro sep, que nos permite indicar el delimitador del fichero:
Como primer argumento, le tendremos que pasar la ruta en la cual se encuentra el fichero .csv que queremos leer
Por ejemplo /Users/alumno/fichero.csv
El resultado será un dataframe con distintas columnas.
Primero, nos descargamos el fichero de datos al entorno de ejecución de Google Colab:
%%bash
FILE=employees.csv
wget -O $FILE https://umubox.um.es/index.php/s/PeublREeVAOxiAd/download
--2025-02-07 17:04:06-- https://umubox.um.es/index.php/s/PeublREeVAOxiAd/download
Resolving umubox.um.es (umubox.um.es)... 155.54.212.96, 2001:720:1710:212::1:b
Connecting to umubox.um.es (umubox.um.es)|155.54.212.96|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 59175 (58K) [text/csv]
Saving to: ‘employees.csv’
0K .......... .......... .......... .......... .......... 86% 315K 0s
50K ....... 100% 121K=0.2s
2025-02-07 17:04:07 (260 KB/s) - ‘employees.csv’ saved [59175/59175]
Lo primero será importar Pandas:
# Para cargar el módulo de Pandas
import pandas
# o bien
import pandas as pd
# Le indicamos la ruta del fichero, y que estará separado por comas.
dataFrame = pd.read_csv("employees.csv", sep = ",")
dataFrame
| First Name | Gender | Start Date | Last Login Time | Salary | Bonus % | Senior Management | Team | |
|---|---|---|---|---|---|---|---|---|
| 0 | Douglas | Male | 8/6/1993 | 12:42 PM | 97308 | 6.945 | True | Marketing |
| 1 | Thomas | Male | 3/31/1996 | 6:53 AM | 61933 | 4.170 | True | NaN |
| 2 | Maria | Female | 4/23/1993 | 11:17 AM | 130590 | 11.858 | False | Finance |
| 3 | Jerry | Male | 3/4/2005 | 1:00 PM | 138705 | 9.340 | True | Finance |
| 4 | Larry | Male | 1/24/1998 | 4:47 PM | 101004 | 1.389 | True | Client Services |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 995 | Henry | NaN | 11/23/2014 | 6:09 AM | 132483 | 16.655 | False | Distribution |
| 996 | Phillip | Male | 1/31/1984 | 6:30 AM | 42392 | 19.675 | False | Finance |
| 997 | Russell | Male | 5/20/2013 | 12:39 PM | 96914 | 1.421 | False | Product |
| 998 | Larry | Male | 4/20/2013 | 4:45 PM | 60500 | 11.985 | False | Business Development |
| 999 | Albert | Male | 5/15/2012 | 6:24 PM | 129949 | 10.169 | True | Sales |
1000 rows × 8 columns
Además, esta función también nos da la opción de no leer las n primeras filas del fichero:
dataFrame = pd.read_csv("employees.csv", sep = ",", skiprows = 900, header=None)
dataFrame
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
|---|---|---|---|---|---|---|---|---|
| 0 | Walter | Male | 5/21/1992 | 12:39 AM | 144701 | 16.323 | True | Marketing |
| 1 | Christina | Female | 6/23/2002 | 3:18 PM | 35477 | 18.178 | False | Human Resources |
| 2 | Patricia | Female | 10/10/1995 | 4:52 PM | 119266 | 6.911 | False | Distribution |
| 3 | NaN | Male | 5/23/2001 | 7:52 PM | 103877 | 6.322 | NaN | Distribution |
| 4 | Heather | Female | 7/29/1983 | 10:48 AM | 47605 | 14.955 | True | Human Resources |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 96 | Henry | NaN | 11/23/2014 | 6:09 AM | 132483 | 16.655 | False | Distribution |
| 97 | Phillip | Male | 1/31/1984 | 6:30 AM | 42392 | 19.675 | False | Finance |
| 98 | Russell | Male | 5/20/2013 | 12:39 PM | 96914 | 1.421 | False | Product |
| 99 | Larry | Male | 4/20/2013 | 4:45 PM | 60500 | 11.985 | False | Business Development |
| 100 | Albert | Male | 5/15/2012 | 6:24 PM | 129949 | 10.169 | True | Sales |
101 rows × 8 columns
Si no existiesen las cabeceras de cada columna o quisiésemos usar otras distintas a las del conjunto de datos original, podemos asignarlas manualmente:
names = ["First Name","Gender","Start Date","Last Login Time","Salary", "Bonus %","Senior Management","Team"]
dataFrame = pd.read_csv("employees.csv", sep = ",", skiprows = 900, header=None, names=names)
dataFrame
| First Name | Gender | Start Date | Last Login Time | Salary | Bonus % | Senior Management | Team | |
|---|---|---|---|---|---|---|---|---|
| 0 | Walter | Male | 5/21/1992 | 12:39 AM | 144701 | 16.323 | True | Marketing |
| 1 | Christina | Female | 6/23/2002 | 3:18 PM | 35477 | 18.178 | False | Human Resources |
| 2 | Patricia | Female | 10/10/1995 | 4:52 PM | 119266 | 6.911 | False | Distribution |
| 3 | NaN | Male | 5/23/2001 | 7:52 PM | 103877 | 6.322 | NaN | Distribution |
| 4 | Heather | Female | 7/29/1983 | 10:48 AM | 47605 | 14.955 | True | Human Resources |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 96 | Henry | NaN | 11/23/2014 | 6:09 AM | 132483 | 16.655 | False | Distribution |
| 97 | Phillip | Male | 1/31/1984 | 6:30 AM | 42392 | 19.675 | False | Finance |
| 98 | Russell | Male | 5/20/2013 | 12:39 PM | 96914 | 1.421 | False | Product |
| 99 | Larry | Male | 4/20/2013 | 4:45 PM | 60500 | 11.985 | False | Business Development |
| 100 | Albert | Male | 5/15/2012 | 6:24 PM | 129949 | 10.169 | True | Sales |
101 rows × 8 columns
E incluso podemos leer solo las columnas que elijamos:
dataFrame = pd.read_csv("employees.csv", sep = ",", usecols = ['First Name','Gender'])
dataFrame
| First Name | Gender | |
|---|---|---|
| 0 | Douglas | Male |
| 1 | Thomas | Male |
| 2 | Maria | Female |
| 3 | Jerry | Male |
| 4 | Larry | Male |
| ... | ... | ... |
| 995 | Henry | NaN |
| 996 | Phillip | Male |
| 997 | Russell | Male |
| 998 | Larry | Male |
| 999 | Albert | Male |
1000 rows × 2 columns
DataFrames¶Además de obtener un DataFrame a partir de un fichero de disco, también existen otras formas de crear DataFrames.
Por ejemplo, podemos crear un DataFrame a partir de un diccionario:
datos = {'nombre':['María', 'Luis', 'Carmen', 'Antonio'],
'apellidos': ['López Martínez', 'Tortosa Riquelme', 'Galindo Pérez', 'Guillén Gómez'],
'edad':[21, 21, 22, 21],
'grado':['GICD', 'GICD', 'GICD', 'Comunicación audiovisual'],
'correo':['maria@um.es', 'luis@um.es', 'carmen@um.es', 'antonio@um.es']
}
df = pd.DataFrame(datos)
df
| nombre | apellidos | edad | grado | correo | |
|---|---|---|---|---|---|
| 0 | María | López Martínez | 21 | GICD | maria@um.es |
| 1 | Luis | Tortosa Riquelme | 21 | GICD | luis@um.es |
| 2 | Carmen | Galindo Pérez | 22 | GICD | carmen@um.es |
| 3 | Antonio | Guillén Gómez | 21 | Comunicación audiovisual | antonio@um.es |
También podemos crear el mismo DataFrame haciendo uso de una lista de listas. En este caso, cada lista no representa todos los valores de una misma columna, si no los valores de una fila. Además, tendremos que indicarle el nombre de las columnas:
datos = [['María', 'López Martínez', 21, 'GICD', 'maria@um.es'],
['Luis', 'Tortosa Riquelme', 21, 'GICD', 'luis@um.es'],
['Carmen', 'Galindo Pérez', 22, 'GICD', 'carmen@um.es'],
['Antonio', 'Guillén Gómez', 21, 'Comunicación audiovisual', 'antonio@um.es']]
df = pd.DataFrame(datos, columns=['nombre', 'apellidos', 'edad', 'grado', 'email'])
df
| nombre | apellidos | edad | grado | ||
|---|---|---|---|---|---|
| 0 | María | López Martínez | 21 | GICD | maria@um.es |
| 1 | Luis | Tortosa Riquelme | 21 | GICD | luis@um.es |
| 2 | Carmen | Galindo Pérez | 22 | GICD | carmen@um.es |
| 3 | Antonio | Guillén Gómez | 21 | Comunicación audiovisual | antonio@um.es |
Por último, también se pueden crear dichas estructuras a partir de listas de diccionarios:
datos = [
{'nombre': 'María', 'apellidos': 'López Martínez', 'edad': 21, 'grado': 'GICD', 'email': 'maria@um.es'},
{'nombre': 'Luis', 'apellidos': 'Tortosa Riquelme', 'edad': 21, 'grado': 'GICD', 'email': 'luis@um.es'},
{'nombre': 'Carmen', 'apellidos': 'Galindo Pérez', 'edad': 22, 'grado': 'GICD', 'email': 'carmen@um.es'},
{'nombre': 'Antonio', 'apellidos': 'Guillén Gómez', 'edad': 21, 'grado': 'Comunicación audiovisual', 'email': 'antonio@um.es'},
{'nombre': 'Manuel','grado': 'Comunicación audiovisual'}
]
df = pd.DataFrame(datos)
df
| nombre | apellidos | edad | grado | ||
|---|---|---|---|---|---|
| 0 | María | López Martínez | 21.0 | GICD | maria@um.es |
| 1 | Luis | Tortosa Riquelme | 21.0 | GICD | luis@um.es |
| 2 | Carmen | Galindo Pérez | 22.0 | GICD | carmen@um.es |
| 3 | Antonio | Guillén Gómez | 21.0 | Comunicación audiovisual | antonio@um.es |
| 4 | Manuel | NaN | NaN | Comunicación audiovisual | NaN |
En este caso, cada diccionario representa una fila de la tabla, con las claves como nombre de columna. Como vemos, si introducimos una fila que tiene valores faltantes en ciertas columnas, se rellena con NaN.
DataFrame¶Podemos añadir columnas a un DataFrame existente de forma similar a como añadir un par clave-valor a un diccionario:
# Nueva columna
df['Nota media'] = [5.6, 6.4, 6.9, 8.3, 5.9]
df
| nombre | apellidos | edad | grado | Nota media | ||
|---|---|---|---|---|---|---|
| 0 | María | López Martínez | 21.0 | GICD | maria@um.es | 5.6 |
| 1 | Luis | Tortosa Riquelme | 21.0 | GICD | luis@um.es | 6.4 |
| 2 | Carmen | Galindo Pérez | 22.0 | GICD | carmen@um.es | 6.9 |
| 3 | Antonio | Guillén Gómez | 21.0 | Comunicación audiovisual | antonio@um.es | 8.3 |
| 4 | Manuel | NaN | NaN | Comunicación audiovisual | NaN | 5.9 |
Ya que los datos de una misma columna son del mismo tipo, podemos aplicar operaciones de forma sencilla a todos los elementos:
# Volvemos a leer nuestro DataFrame completo
dataFrame = pd.read_csv("employees.csv", sep = ",")
dataFrame.head()
| First Name | Gender | Start Date | Last Login Time | Salary | Bonus % | Senior Management | Team | |
|---|---|---|---|---|---|---|---|---|
| 0 | Douglas | Male | 8/6/1993 | 12:42 PM | 97308 | 6.945 | True | Marketing |
| 1 | Thomas | Male | 3/31/1996 | 6:53 AM | 61933 | 4.170 | True | NaN |
| 2 | Maria | Female | 4/23/1993 | 11:17 AM | 130590 | 11.858 | False | Finance |
| 3 | Jerry | Male | 3/4/2005 | 1:00 PM | 138705 | 9.340 | True | Finance |
| 4 | Larry | Male | 1/24/1998 | 4:47 PM | 101004 | 1.389 | True | Client Services |
# Operacion de comparación
dataFrame['Salary'] > 100000
| Salary | |
|---|---|
| 0 | False |
| 1 | False |
| 2 | True |
| 3 | True |
| 4 | True |
| ... | ... |
| 995 | True |
| 996 | False |
| 997 | False |
| 998 | False |
| 999 | True |
1000 rows × 1 columns
Además de operaciones simples, podemos aplicar funciones completas a columnas utilizando el método apply(funcion):
def calculoAleatorio(numero):
return round(numero * 2 / 3 + 200, 2)
calculoAleatorio(2)
201.33
# Aplicamos la función a todos los valores de la columna salary
dataFrame['Salary'].apply(calculoAleatorio)
| Salary | |
|---|---|
| 0 | 65072.00 |
| 1 | 41488.67 |
| 2 | 87260.00 |
| 3 | 92670.00 |
| 4 | 67536.00 |
| ... | ... |
| 995 | 88522.00 |
| 996 | 28461.33 |
| 997 | 64809.33 |
| 998 | 40533.33 |
| 999 | 86832.67 |
1000 rows × 1 columns
DataFrame que hemos leído a través del CSV, multiplica el bonus de las empleadas por 1.5. Para ello, tendrás que:¶DataFrame y comprobar si es un empleado o empleada mediante una estructura condicional.¶Bonus.¶Respuesta 1:
# Responde aquí
for _, row in dataFrame.iterrows():
print(row['Bonus %'])
6.945 4.17 17.787 9.34 1.389 10.125 15.018 17.397000000000002 27.7845 11.286 22.698 18.9555 17.492 5.831 21.8145 1.884 7.369 6.414 28.623 2.8409999999999997 4.934 13.645 18.816 5.042 13.873 18.576 7.757 5.218 13.464 7.008 13.644 12.752 6.417 24.27 19.096 25.012500000000003 18.8985 14.3355 8.361 7.797 2.665 11.308 23.7525 7.810499999999999 11.223 13.886 6.796 13.5 6.083 3.055 20.745 14.009 1.695 17.578 13.4985 26.479499999999998 16.084 15.107 2.2215000000000003 16.9185 4.271 5.5485 29.121000000000002 18.04 18.771 12.428 4.008 14.6025 14.33 4.382 6.617 16.194 3.833 7.0634999999999994 17.029 7.6770000000000005 11.029499999999999 1.26 8.9475 7.485 15.602 14.822 8.379 6.539 11.2665 3.887 17.29 12.414 9.2325 17.9325 11.583 8.309 18.759 1.601 7.03 21.249000000000002 2.6055 10.62 25.441499999999998 12.447 22.4925 11.849 12.159 13.398 19.305 12.8505 3.046 16.565 12.396 11.449 24.2025 12.681000000000001 4.023 5.5665 10.2165 6.2490000000000006 18.988 9.494 14.3355 12.299 15.402 18.74 20.838 22.261499999999998 3.6014999999999997 21.339000000000002 25.768499999999996 5.83 16.439 13.101 9.3285 26.2755 10.763 3.3525 3.9749999999999996 13.249500000000001 19.687 15.12 9.045 15.790499999999998 2.781 14.727 8.5305 8.689 12.452 19.6185 6.2250000000000005 3.996 14.837 12.866999999999999 19.934 15.295 12.1005 10.489 8.038499999999999 26.5425 1.563 21.6645 13.134 14.316 25.4865 11.451 14.422 19.135 27.295499999999997 13.5915 10.521 17.984 7.017 8.182500000000001 28.53 17.495 14.102999999999998 5.9385 6.185 1.451 10.166 14.085 26.472 29.014499999999998 5.025 1.952 18.276 2.518 9.177 13.263000000000002 2.7375 6.46 15.931 1.215 13.6935 9.978 16.475 6.664499999999999 13.494 12.757 19.127 4.5465 14.46 16.736 8.525 11.9295 5.084 4.176 4.935 8.012 12.598499999999998 2.6505 4.903 16.9425 13.722 29.418 2.7315 23.046 5.324999999999999 5.699999999999999 2.462 1.015 10.628 7.768 8.34 3.845 3.067 15.866 3.4665 15.266 14.106 11.226 17.445 1.679 8.999 25.527 15.3945 22.128 18.273 5.464499999999999 3.936 14.0625 5.128 17.612 19.107 5.961 18.428 5.413 8.866 17.138 12.045 3.742 4.366 29.325000000000003 8.94 6.513 4.232 10.391 7.995 7.661999999999999 7.125 15.517 12.659 15.585 3.7365000000000004 20.5155 5.5845 14.603 19.826999999999998 3.45 21.0945 16.044 8.715 27.7755 9.554 12.062 18.225 1.113 5.46 27.683999999999997 17.994 19.062 19.476 1.7085 9.635 6.147 12.345 1.612 6.5055 3.4559999999999995 10.985 14.9985 18.099 9.582 13.657 26.1945 27.426 9.653 28.731 3.873 3.18 7.664 4.542 28.541999999999998 3.592 13.023 5.027 3.657 18.702 5.5995 17.44 4.4055 3.2940000000000005 15.794 2.158 13.448 1.923 20.1855 6.338 15.858 16.448999999999998 12.51 1.841 27.3645 21.534 11.2605 14.372 4.5615 9.0465 17.885 12.075 5.097 5.319 14.987 7.887 25.903499999999998 18.645 11.241 1.844 19.93 12.182 4.035 10.717 16.443 2.846 11.58 15.3705 4.99 3.914 6.96 5.778 21.334500000000002 19.897 13.084500000000002 3.95 16.1265 4.844 3.095 2.673 18.1815 8.502 7.843 4.45 11.736 28.338 6.117000000000001 9.555 13.865 3.595 1.113 16.231 10.957 13.122 18.726 3.291 5.14 19.717 12.072 4.7565 4.805 4.664 10.574 9.669 6.8055 5.66 10.894 18.273 2.362 15.723 13.3425 25.045499999999997 19.894 16.968 10.413 13.443 14.983500000000001 4.03 6.976 7.5375000000000005 10.641 29.0775 13.835 11.1375 11.698500000000001 18.241 13.953 14.272 19.642 8.86 11.346 26.307000000000002 9.55 1.62 19.276 6.191 11.699 21.9135 5.861 11.9 12.699 5.966 9.047 3.9960000000000004 4.68 19.334 18.021 16.261 26.154 14.637 3.567 3.56 8.037 7.869 8.445 29.133000000000003 7.077 12.993 10.698 21.3405 10.069 17.796 16.794 6.22 2.826 11.343 2.8289999999999997 3.7769999999999997 27.738 7.008 1.496 23.775 11.204 17.066 5.4975000000000005 19.691 19.49 1.965 6.507 10.429 27.0435 6.662 24.936 15.843 5.574 21.372 13.946 7.996 3.269 18.641 6.282 5.461 12.332999999999998 16.044 9.078 11.466 22.0395 8.047 8.457 11.364 11.9055 12.691500000000001 9.705 18.357 18.787 23.9505 1.6275 3.38 4.6485 11.119 2.9775 2.021 23.877 19.944 29.596500000000002 11.191500000000001 6.525 18.845 13.266 10.875 2.117 5.437 7.123 6.822 14.764 16.689 9.765 2.6445 4.887 15.741 13.248 6.499 18.654 15.592 9.33 17.07 8.13 29.5425 19.624 18.115 10.458 23.9685 5.9955 27.0045 3.178 8.411 17.971 22.287 22.539 14.509 9.54 13.044 1.022 7.175 7.252 21.892500000000002 15.231 15.419999999999998 13.773 12.292 12.307500000000001 4.905 20.208 3.491 3.459 7.23 11.7765 21.1155 3.5490000000000004 13.32 9.048 3.672 15.549 4.9665 4.779 16.304 19.122 17.857499999999998 20.7795 6.007 27.6765 6.639 27.1725 19.9425 9.765 2.097 12.857999999999999 18.863 14.842 7.563 25.994999999999997 12.986 18.9075 28.713 10.1595 2.1465 18.623 16.69 8.1525 11.1315 5.809 14.879 11.393 2.157 1.187 18.089 15.118 10.2 20.259 18.266 4.131 11.3775 13.4175 3.6285 14.4855 20.019 11.712 15.221 6.966 2.075 5.268 6.752 12.441 17.259 16.387500000000003 15.749 9.862 15.704 12.49 15.427 3.213 15.384 12.74 25.911 15.91 10.084 12.525 7.099 11.378 11.513 6.083 19.3935 2.1765 1.268 28.596 8.4 18.824 13.4985 14.401500000000002 12.2 13.0515 4.3950000000000005 24.954 1.702 29.2695 2.617 1.869 10.317 9.75 19.289 13.047 4.386 18.396 2.1495 19.391 5.6339999999999995 7.804500000000001 15.108 9.77 28.368 10.162 29.67 5.32 15.857 21.096 17.6235 26.0565 1.017 25.383000000000003 11.411 13.613 25.662 17.0505 20.386499999999998 4.785 6.662 4.225 6.9885 19.299 12.463 3.645 7.776 14.771 17.105 11.879 22.173000000000002 5.9399999999999995 10.982 16.248 1.932 19.186500000000002 14.7015 23.655 4.012499999999999 5.0175 14.301 17.398 7.901999999999999 6.611 15.7275 19.387 18.704 8.992 17.821 17.263 13.926 5.541 8.162 4.173 19.989 7.718999999999999 11.593 9.801 8.218 10.385 7.927 11.712 10.464 9.769 11.211 15.193 18.473 11.758500000000002 1.197 12.048 17.095 24.828 15.745 14.776500000000002 12.922 13.132 13.806 11.518 7.969 13.001 28.027499999999996 11.626 5.197 11.416 20.205000000000002 1.876 13.0 12.942 28.6665 18.892 28.011 19.158 1.432 3.655 2.0999999999999996 10.2555 17.573999999999998 14.618 12.737 14.737 3.533 23.9115 2.844 13.813 5.19 14.625 1.5404999999999998 16.559 29.439 9.712 16.379 5.0535000000000005 18.338 5.478 3.045 5.9955 10.615 7.783 7.617 16.3425 4.02 15.009 3.947 4.5285 15.343 11.479 9.699 28.153499999999998 14.49 9.849 19.767000000000003 12.026 27.027 10.736 16.3005 9.09 18.784 6.7695 5.266 26.6985 16.843 9.127 17.68 13.592 5.1795 13.4115 3.87 4.135 16.353 9.4395 11.058 19.601 9.564 20.5605 15.428999999999998 3.319 19.2015 29.775000000000002 17.952 2.712 11.517 17.499 20.4345 28.612499999999997 10.664 15.081 9.121500000000001 3.1334999999999997 5.1885 19.754 7.227 10.227 5.478 29.6505 4.8315 4.0 6.101999999999999 6.1245 15.072 17.862 5.182 18.381 10.899000000000001 9.494 3.2204999999999995 5.89 5.665 7.487 11.796 2.097 19.908 7.588 19.467 9.331 2.071 2.28 20.238 15.804 9.153 25.210499999999996 7.386000000000001 29.2515 28.896 13.4475 8.738 17.523 15.574 4.707 2.88 9.192 6.002 16.158 26.014499999999998 17.085 10.411 2.277 12.211 11.9145 9.634 28.8585 14.66 18.855 18.536 6.842 6.01 24.459000000000003 21.3735 7.737 20.485500000000002 7.986 18.751 2.469 28.998 4.299 5.2875 13.818 8.219 13.823 12.096 28.698 8.382 9.477 14.344 27.0225 27.795 9.16 14.837 15.407 17.901 2.3280000000000003 7.1 8.475 2.709 5.681 11.4675 16.968 3.942 10.146 22.8165 16.323 27.267000000000003 10.366499999999998 6.322 22.4325 9.24 6.544500000000001 26.500500000000002 15.1215 4.9245 6.466 13.3185 15.528 1.02 9.252 7.908 6.716 11.544 6.339 19.475 8.957 14.741999999999999 18.9 3.412 4.38 14.436 29.082 29.232 16.014 2.673 1.6185 3.579 3.771 3.0149999999999997 5.6985 3.787 18.134999999999998 15.084 18.424 2.657 2.147 8.611 15.653 9.8055 2.728 1.905 17.426 25.411499999999997 5.329 16.572 8.226 16.2495 14.493000000000002 17.860500000000002 14.077 1.148 16.764 12.1725 15.901 14.4465 5.85 18.093 3.05 16.923 26.910000000000004 12.391 27.5895 9.146 19.572 17.5065 25.962 23.0955 5.368 11.159 11.105 16.455 18.7005 6.2925 8.9235 11.178 13.198 13.293 19.28 12.958499999999999 11.738 19.56 1.909 26.9985 15.4965 16.813499999999998 3.794 16.473 16.5765 11.625 28.56 4.479 16.655 19.675 1.421 11.985 10.169
DataFrames¶La operación básica de filtrado es seleccionar aquellos valores que cumplen una condición. Para ello se puede comparar la columna con el valor deseado y obtener una lista de valores verdaderos o falsos. Por ejemplo, en el caso de los salarios que son mayores a 100000:
dataFrame['Salary'] > 100000
| Salary | |
|---|---|
| 0 | False |
| 1 | False |
| 2 | True |
| 3 | True |
| 4 | True |
| ... | ... |
| 995 | True |
| 996 | False |
| 997 | False |
| 998 | False |
| 999 | True |
1000 rows × 1 columns
Ahora, para obtener un nuevo DataFrame solamente con estas personas seleccionadas, tenemos que usar el resultado anterior como filtro. Lo podemos hacer de la siguiente manera:
# Nos quedamos solo con las columnas cuyo salario sea mayor de 100.000
dataFrame[dataFrame['Salary'] > 100000]
| First Name | Gender | Start Date | Last Login Time | Salary | Bonus % | Senior Management | Team | |
|---|---|---|---|---|---|---|---|---|
| 2 | Maria | Female | 4/23/1993 | 11:17 AM | 130590 | 11.858 | False | Finance |
| 3 | Jerry | Male | 3/4/2005 | 1:00 PM | 138705 | 9.340 | True | Finance |
| 4 | Larry | Male | 1/24/1998 | 4:47 PM | 101004 | 1.389 | True | Client Services |
| 5 | Dennis | Male | 4/18/1987 | 1:35 AM | 115163 | 10.125 | False | Legal |
| 9 | Frances | Female | 8/8/2002 | 6:51 AM | 139852 | 7.524 | True | Business Development |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 990 | Robin | Female | 7/24/1987 | 1:35 PM | 100765 | 10.982 | True | Client Services |
| 991 | Rose | Female | 8/25/2002 | 5:12 AM | 134505 | 11.051 | True | Marketing |
| 992 | Anthony | Male | 10/16/2011 | 8:35 AM | 112769 | 11.625 | True | Finance |
| 995 | Henry | NaN | 11/23/2014 | 6:09 AM | 132483 | 16.655 | False | Distribution |
| 999 | Albert | Male | 5/15/2012 | 6:24 PM | 129949 | 10.169 | True | Sales |
409 rows × 8 columns
También podemos filtrar usando más de una condición. Para ello, tendremos que especificar el operador entre ambas condiciones:
& (AND) Ambas condiciones deben cumplirse para que la fila sea seleccionada.| (OR) Cada fila será seleccionada siempre y cuando se cumpla al menos una de las condiciones.dataFrame[(dataFrame['Salary'] > 100000) & (dataFrame['Gender'] == 'Female')]
| First Name | Gender | Start Date | Last Login Time | Salary | Bonus % | Senior Management | Team | |
|---|---|---|---|---|---|---|---|---|
| 2 | Maria | Female | 4/23/1993 | 11:17 AM | 130590 | 11.858 | False | Finance |
| 9 | Frances | Female | 8/8/2002 | 6:51 AM | 139852 | 7.524 | True | Business Development |
| 11 | Julie | Female | 10/26/1997 | 3:19 PM | 102508 | 12.637 | True | Legal |
| 18 | Diana | Female | 10/23/1981 | 10:27 AM | 132940 | 19.082 | False | Client Services |
| 30 | Christina | Female | 8/6/2002 | 1:19 PM | 118780 | 9.096 | True | Engineering |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 976 | Denise | Female | 10/19/1992 | 5:42 AM | 137954 | 4.195 | True | Legal |
| 977 | Sarah | Female | 12/4/1995 | 9:16 AM | 124566 | 5.949 | False | Product |
| 987 | Gloria | Female | 12/8/2014 | 5:08 AM | 136709 | 10.331 | True | Finance |
| 990 | Robin | Female | 7/24/1987 | 1:35 PM | 100765 | 10.982 | True | Client Services |
| 991 | Rose | Female | 8/25/2002 | 5:12 AM | 134505 | 11.051 | True | Marketing |
176 rows × 8 columns
Marketing.¶Respuesta 2:
# Resuelve aquí:
groupby()¶Podemos realizar agregaciones por columnas de forma sencilla usando la funcion groupby():
dataFrame.groupby('Gender')
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7c4e78fd8250>
Calculamos la suma acumulativa sobre el objeto creado:
# Suma acumulativa con sum()
dataFrame.groupby("Gender").sum(numeric_only=True)
| Salary | Bonus % | |
|---|---|---|
| Gender | ||
| Female | 38800311 | 4306.127 |
| Male | 38660604 | 4392.570 |
Si quisiéramos realizar la agrupación por más de una columna, bastaría con pasar como argumento una lista con las columnas en cuestión.
dataFrame.groupby(['Gender', 'Team']).sum(numeric_only=True)
| Salary | Bonus % | ||
|---|---|---|---|
| Gender | Team | ||
| Female | Business Development | 4633453 | 512.124 |
| Client Services | 4148644 | 489.447 | |
| Distribution | 3009142 | 366.786 | |
| Engineering | 3973686 | 434.270 | |
| Finance | 4056952 | 399.035 | |
| Human Resources | 3462528 | 382.966 | |
| Legal | 3086873 | 321.179 | |
| Marketing | 3802970 | 413.884 | |
| Product | 3878219 | 443.055 | |
| Sales | 3502768 | 397.958 | |
| Male | Business Development | 3562870 | 426.471 |
| Client Services | 3911957 | 454.915 | |
| Distribution | 3285163 | 306.140 | |
| Engineering | 3936330 | 427.703 | |
| Finance | 3915817 | 442.369 | |
| Human Resources | 4111593 | 443.417 | |
| Legal | 2948913 | 421.216 | |
| Marketing | 3529377 | 416.435 | |
| Product | 3558313 | 383.191 | |
| Sales | 3634670 | 397.737 |
# Media con mean()
dataFrame.groupby('Team').mean(numeric_only=True)
| Salary | Bonus % | |
|---|---|---|
| Team | ||
| Business Development | 91866.316832 | 10.572376 |
| Client Services | 88224.424528 | 10.495104 |
| Distribution | 88500.466667 | 9.615644 |
| Engineering | 94269.195652 | 10.462989 |
| Finance | 92219.480392 | 10.186873 |
| Human Resources | 90944.527473 | 9.993879 |
| Legal | 89303.613636 | 10.322830 |
| Marketing | 90435.591837 | 10.353449 |
| Product | 88665.505263 | 9.791484 |
| Sales | 92173.436170 | 10.116915 |
Tenemos más funciones a nuestra disposición para aplicar múltiples operadores a nuestras agregaciones:
count() Número total de elementos
first(), last() Primer y último elemento
mean(), median() Media y mediana
min(), max() Mínimo y máximo
std(), var() Desviación estándar y varianza
prod() Producto de todos los elementos
sum() Suma de todos los elementos
DataFrame filtrado), obtén la media de los elementos utilizando la agregación y mean().¶Respuesta 3:
# Resuelve aquí:
# Resuelve aquí:
Con la función describe() obtenemos una serie de agregaciones para cada columna númerica, incluyendo la media o el valor máximo, entre otras:
dataFrame.describe()
| Salary | Bonus % | |
|---|---|---|
| count | 1000.000000 | 1000.000000 |
| mean | 90662.181000 | 10.207555 |
| std | 32923.693342 | 5.528481 |
| min | 35013.000000 | 1.015000 |
| 25% | 62613.000000 | 5.401750 |
| 50% | 90428.000000 | 9.838500 |
| 75% | 118740.250000 | 14.838000 |
| max | 149908.000000 | 19.944000 |
df[id_columna]¶# Seleccionamos la columna Gender y lo asignamos a una variable
genero = dataFrame['Gender']
genero
| Gender | |
|---|---|
| 0 | Male |
| 1 | Male |
| 2 | Female |
| 3 | Male |
| 4 | Male |
| ... | ... |
| 995 | NaN |
| 996 | Male |
| 997 | Male |
| 998 | Male |
| 999 | Male |
1000 rows × 1 columns
list(genero)
['Male', 'Male', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', 'Female', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', nan, 'Male', nan, 'Male', 'Male', 'Male', 'Male', nan, 'Male', 'Male', 'Female', nan, 'Male', 'Female', 'Male', 'Female', 'Female', 'Female', 'Female', 'Male', 'Male', nan, 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', nan, 'Female', nan, 'Male', nan, 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', nan, 'Female', 'Female', 'Male', nan, 'Male', 'Female', 'Female', 'Male', nan, nan, 'Male', 'Male', 'Female', 'Male', 'Female', 'Female', 'Male', 'Female', 'Female', nan, 'Male', 'Male', 'Male', 'Female', 'Male', nan, 'Female', 'Female', 'Female', nan, nan, 'Female', nan, 'Male', 'Female', 'Female', nan, 'Female', 'Male', 'Female', 'Male', 'Male', 'Female', 'Male', 'Female', 'Male', 'Male', nan, 'Male', 'Female', 'Female', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', 'Male', nan, 'Female', 'Female', 'Female', 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', 'Female', nan, nan, 'Female', 'Female', 'Male', nan, 'Female', 'Male', nan, 'Female', nan, 'Female', 'Female', 'Male', 'Female', 'Female', nan, 'Female', nan, 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', nan, 'Female', 'Female', 'Male', 'Female', 'Female', nan, 'Male', 'Male', 'Male', 'Female', 'Female', 'Male', 'Male', 'Female', nan, 'Male', 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', nan, 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', 'Female', 'Female', 'Female', 'Female', 'Female', 'Female', 'Male', 'Male', nan, 'Male', 'Female', 'Male', 'Male', 'Male', 'Female', 'Male', 'Female', 'Male', 'Male', 'Male', nan, 'Female', 'Female', 'Female', 'Female', 'Female', 'Female', 'Female', 'Male', nan, nan, 'Male', 'Male', 'Male', 'Male', 'Male', nan, nan, 'Male', 'Female', nan, nan, 'Male', nan, 'Male', 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', 'Female', nan, 'Female', 'Male', 'Female', 'Male', 'Female', 'Female', 'Male', nan, 'Male', 'Male', 'Male', 'Female', 'Female', nan, 'Female', 'Female', 'Male', 'Male', nan, 'Male', 'Female', 'Female', 'Male', 'Female', nan, 'Female', 'Male', 'Female', 'Female', 'Male', 'Female', 'Male', nan, 'Male', nan, 'Female', 'Male', 'Male', 'Male', nan, 'Male', 'Female', 'Male', 'Female', 'Female', 'Male', 'Male', nan, 'Male', 'Female', 'Male', nan, 'Female', 'Female', 'Male', 'Female', 'Female', 'Female', 'Male', 'Female', 'Female', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Female', 'Male', 'Female', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Female', 'Male', 'Male', 'Male', 'Male', 'Female', 'Male', 'Female', nan, 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', nan, 'Male', nan, nan, 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', nan, 'Male', 'Male', 'Male', 'Female', nan, 'Male', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', nan, nan, 'Female', 'Male', nan, 'Female', 'Female', 'Female', 'Male', 'Female', 'Female', nan, 'Female', nan, 'Male', nan, 'Female', 'Female', nan, 'Male', 'Male', 'Male', 'Male', 'Female', 'Male', 'Male', nan, 'Male', nan, 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', nan, 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', 'Male', nan, 'Female', 'Female', 'Male', 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', 'Male', 'Female', 'Male', nan, 'Male', 'Female', 'Male', 'Female', nan, 'Female', 'Male', nan, 'Female', 'Male', 'Male', 'Male', 'Male', 'Female', 'Male', 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', nan, 'Female', 'Male', 'Female', 'Male', 'Female', 'Male', 'Female', 'Female', nan, 'Male', 'Male', 'Female', 'Male', 'Male', 'Male', 'Female', nan, 'Female', 'Male', 'Female', 'Male', 'Female', 'Male', 'Male', 'Male', 'Male', 'Female', 'Male', 'Male', 'Female', 'Male', nan, 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', nan, 'Female', 'Female', nan, 'Male', 'Female', nan, nan, 'Male', 'Female', 'Female', 'Female', 'Male', nan, 'Female', 'Male', 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', 'Female', 'Male', nan, 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', nan, 'Female', 'Male', 'Female', 'Female', 'Female', 'Male', 'Female', nan, 'Male', 'Male', 'Female', 'Male', 'Female', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', 'Male', 'Male', 'Male', 'Male', 'Female', 'Male', 'Female', 'Female', 'Female', 'Female', 'Female', 'Female', 'Female', 'Male', 'Female', 'Male', 'Female', 'Male', 'Female', 'Female', 'Female', nan, nan, nan, nan, 'Male', 'Female', 'Female', 'Male', 'Female', 'Male', 'Male', nan, nan, nan, 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', 'Female', 'Female', nan, 'Female', 'Male', nan, 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', 'Female', nan, 'Female', 'Female', nan, 'Male', 'Female', nan, 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', nan, nan, 'Male', 'Female', 'Female', 'Male', 'Male', nan, nan, 'Male', nan, 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', nan, 'Female', 'Male', nan, 'Male', 'Male', nan, 'Male', 'Female', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', nan, nan, 'Male', nan, 'Female', nan, 'Male', 'Male', 'Male', 'Female', 'Male', 'Male', 'Male', 'Female', nan, 'Female', 'Male', 'Male', 'Male', nan, 'Male', 'Male', 'Female', 'Male', 'Male', nan, 'Female', 'Male', 'Male', 'Male', 'Female', 'Male', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Male', nan, 'Female', 'Male', 'Male', nan, 'Male', 'Female', 'Male', 'Female', nan, nan, 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Male', nan, 'Female', 'Male', 'Female', 'Male', 'Female', 'Male', nan, 'Male', 'Female', 'Female', nan, 'Female', 'Male', 'Female', 'Male', 'Female', 'Female', 'Male', 'Female', 'Male', 'Female', 'Male', 'Male', 'Male', nan, 'Female', 'Female', 'Female', 'Male', nan, 'Female', 'Male', 'Male', nan, 'Female', 'Female', nan, 'Female', 'Female', 'Male', 'Male', 'Male', 'Male', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', 'Female', 'Female', nan, 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', nan, nan, nan, 'Female', 'Male', 'Male', 'Male', 'Male', 'Male', nan, 'Male', 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', 'Female', 'Female', nan, 'Female', 'Male', nan, 'Male', 'Male', 'Male', 'Male', 'Female', 'Female', 'Male', nan, nan, 'Female', 'Male', 'Female', 'Male', 'Male', 'Male', 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', 'Male', nan, 'Male', 'Female', 'Male', 'Female', 'Female', nan, 'Male', 'Female', 'Female', nan, 'Female', nan, 'Female', 'Female', 'Male', 'Male', 'Male', 'Female', 'Female', 'Male', 'Male', 'Male', 'Male', 'Female', nan, 'Male', nan, 'Female', 'Male', 'Female', 'Female', 'Male', 'Female', 'Female', 'Female', 'Female', 'Female', 'Female', 'Male', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', 'Male', 'Male', 'Male', 'Female', 'Male', 'Male', nan, 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', 'Female', 'Male', 'Female', 'Female', nan, nan, nan, 'Male', 'Male', 'Female', 'Male', 'Male', nan, 'Female', 'Male', 'Female', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Female', 'Male', 'Female', 'Male', 'Male', nan, 'Male', 'Female', 'Male', 'Female', 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', nan, 'Male', 'Male', 'Female', 'Female', 'Female', 'Male', 'Male', 'Female', 'Male', 'Female', 'Male', 'Female', nan, 'Female', 'Female', 'Female', nan, 'Female', 'Female', 'Male', 'Female', 'Male', nan, 'Male', 'Male', 'Male', 'Male']
Podemos ver los valores únicos que existen en cada columno haciendo uso de los set (conjuntos).
Recordemos que los conjuntos se manejan de manera similar a las listas, pero en estos no existen los valores repetidos:
set(genero)
{'Female', 'Male', nan}
# Para eliminar los valores nulos en una columna, podemos hacer uso de dropna():
generoSinNulos = genero.dropna()
generoSinNulos
| Gender | |
|---|---|
| 0 | Male |
| 1 | Male |
| 2 | Female |
| 3 | Male |
| 4 | Male |
| ... | ... |
| 994 | Male |
| 996 | Male |
| 997 | Male |
| 998 | Male |
| 999 | Male |
855 rows × 1 columns
set(generoSinNulos)
{'Female', 'Male'}
# Borra todas las filas con valores nulos del dataframe
# La opción inplace indica si queremos que se aplique en el dataframe existente antes o no
dataFrameSinNulos = dataFrame.dropna(inplace=False)
dataFrame
| First Name | Gender | Start Date | Last Login Time | Salary | Bonus % | Senior Management | Team | |
|---|---|---|---|---|---|---|---|---|
| 0 | Douglas | Male | 8/6/1993 | 12:42 PM | 97308 | 6.945 | True | Marketing |
| 2 | Maria | Female | 4/23/1993 | 11:17 AM | 130590 | 11.858 | False | Finance |
| 3 | Jerry | Male | 3/4/2005 | 1:00 PM | 138705 | 9.340 | True | Finance |
| 4 | Larry | Male | 1/24/1998 | 4:47 PM | 101004 | 1.389 | True | Client Services |
| 5 | Dennis | Male | 4/18/1987 | 1:35 AM | 115163 | 10.125 | False | Legal |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 994 | George | Male | 6/21/2013 | 5:47 PM | 98874 | 4.479 | True | Marketing |
| 996 | Phillip | Male | 1/31/1984 | 6:30 AM | 42392 | 19.675 | False | Finance |
| 997 | Russell | Male | 5/20/2013 | 12:39 PM | 96914 | 1.421 | False | Product |
| 998 | Larry | Male | 4/20/2013 | 4:45 PM | 60500 | 11.985 | False | Business Development |
| 999 | Albert | Male | 5/15/2012 | 6:24 PM | 129949 | 10.169 | True | Sales |
764 rows × 8 columns
dataFrameSinNulos
| First Name | Gender | Start Date | Last Login Time | Salary | Bonus % | Senior Management | Team | |
|---|---|---|---|---|---|---|---|---|
| 0 | Douglas | Male | 8/6/1993 | 12:42 PM | 97308 | 6.945 | True | Marketing |
| 2 | Maria | Female | 4/23/1993 | 11:17 AM | 130590 | 11.858 | False | Finance |
| 3 | Jerry | Male | 3/4/2005 | 1:00 PM | 138705 | 9.340 | True | Finance |
| 4 | Larry | Male | 1/24/1998 | 4:47 PM | 101004 | 1.389 | True | Client Services |
| 5 | Dennis | Male | 4/18/1987 | 1:35 AM | 115163 | 10.125 | False | Legal |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 994 | George | Male | 6/21/2013 | 5:47 PM | 98874 | 4.479 | True | Marketing |
| 996 | Phillip | Male | 1/31/1984 | 6:30 AM | 42392 | 19.675 | False | Finance |
| 997 | Russell | Male | 5/20/2013 | 12:39 PM | 96914 | 1.421 | False | Product |
| 998 | Larry | Male | 4/20/2013 | 4:45 PM | 60500 | 11.985 | False | Business Development |
| 999 | Albert | Male | 5/15/2012 | 6:24 PM | 129949 | 10.169 | True | Sales |
764 rows × 8 columns
pd.concat()¶Primero, vamos a crear dos sub-dataframes a partir del ya existente, seleccionando las 20 primeras filas para el primer sub-conjunto y las 20 siguientes para el segundo:
# Primeras 20 filas
datos1 = dataFrame[0:20]
# Siguientes 20 filas
datos2 = dataFrame[20:40]
datos3 = dataFrame[60:70]
A la funcion pd.concat() tenemos que pasarle como argumento una lista que contenga los distintos DataFrames que queremos unir:
listadf = [datos1, datos2]
pd.concat(listadf)
# o más sencillo
pd.concat([datos1, datos2, datos3])
| First Name | Gender | Start Date | Last Login Time | Salary | Bonus % | Senior Management | Team | |
|---|---|---|---|---|---|---|---|---|
| 0 | Douglas | Male | 8/6/1993 | 12:42 PM | 97308 | 6.945 | True | Marketing |
| 2 | Maria | Female | 4/23/1993 | 11:17 AM | 130590 | 11.858 | False | Finance |
| 3 | Jerry | Male | 3/4/2005 | 1:00 PM | 138705 | 9.340 | True | Finance |
| 4 | Larry | Male | 1/24/1998 | 4:47 PM | 101004 | 1.389 | True | Client Services |
| 5 | Dennis | Male | 4/18/1987 | 1:35 AM | 115163 | 10.125 | False | Legal |
| 6 | Ruby | Female | 8/17/1987 | 4:20 PM | 65476 | 10.012 | True | Product |
| 8 | Angela | Female | 11/22/2005 | 6:29 AM | 95570 | 18.523 | True | Engineering |
| 9 | Frances | Female | 8/8/2002 | 6:51 AM | 139852 | 7.524 | True | Business Development |
| 11 | Julie | Female | 10/26/1997 | 3:19 PM | 102508 | 12.637 | True | Legal |
| 12 | Brandon | Male | 12/1/1980 | 1:08 AM | 112807 | 17.492 | True | Human Resources |
| 13 | Gary | Male | 1/27/2008 | 11:40 PM | 109831 | 5.831 | False | Sales |
| 14 | Kimberly | Female | 1/14/1999 | 7:13 AM | 41426 | 14.543 | True | Finance |
| 15 | Lillian | Female | 6/5/2016 | 6:09 AM | 59414 | 1.256 | False | Product |
| 16 | Jeremy | Male | 9/21/2010 | 5:56 AM | 90370 | 7.369 | False | Human Resources |
| 17 | Shawn | Male | 12/7/1986 | 7:45 PM | 111737 | 6.414 | False | Product |
| 18 | Diana | Female | 10/23/1981 | 10:27 AM | 132940 | 19.082 | False | Client Services |
| 19 | Donna | Female | 7/22/2010 | 3:48 AM | 81014 | 1.894 | False | Product |
| 21 | Matthew | Male | 9/5/1995 | 2:12 AM | 100612 | 13.645 | False | Marketing |
| 24 | John | Male | 7/1/1992 | 10:08 PM | 97950 | 13.873 | False | Client Services |
| 26 | Craig | Male | 2/27/2000 | 7:45 AM | 37598 | 7.757 | True | Marketing |
| 28 | Terry | Male | 11/27/1981 | 6:30 PM | 124008 | 13.464 | True | Client Services |
| 29 | Benjamin | Male | 1/26/2005 | 10:06 PM | 79529 | 7.008 | True | Legal |
| 30 | Christina | Female | 8/6/2002 | 1:19 PM | 118780 | 9.096 | True | Engineering |
| 33 | Jean | Female | 12/18/1993 | 9:07 AM | 119082 | 16.180 | False | Business Development |
| 34 | Jerry | Male | 1/10/2004 | 12:56 PM | 95734 | 19.096 | False | Client Services |
| 35 | Theresa | Female | 10/10/2006 | 1:12 AM | 85182 | 16.675 | False | Sales |
| 36 | Rachel | Female | 2/16/2009 | 8:47 PM | 142032 | 12.599 | False | Business Development |
| 37 | Linda | Female | 10/19/1981 | 8:49 PM | 57427 | 9.557 | True | Client Services |
| 38 | Stephanie | Female | 9/13/1986 | 1:52 AM | 36844 | 5.574 | True | Business Development |
| 40 | Michael | Male | 10/10/2008 | 11:25 AM | 99283 | 2.665 | True | Distribution |
| 42 | Beverly | Female | 9/9/1998 | 8:26 PM | 121918 | 15.835 | False | Legal |
| 43 | Marilyn | Female | 12/7/1980 | 3:16 AM | 73524 | 5.207 | True | Marketing |
| 44 | Cynthia | Female | 11/16/1988 | 6:54 PM | 145146 | 7.482 | True | Product |
| 45 | Roger | Male | 4/17/1980 | 11:32 AM | 88010 | 13.886 | True | Sales |
| 46 | Bruce | Male | 11/28/2009 | 10:47 PM | 114796 | 6.796 | False | Finance |
| 47 | Kathy | Female | 6/22/2005 | 4:51 AM | 66820 | 9.000 | True | Client Services |
| 48 | Clarence | Male | 3/26/1996 | 5:57 AM | 93581 | 6.083 | True | Business Development |
| 50 | Nancy | Female | 9/23/2000 | 8:05 AM | 94976 | 13.830 | True | Engineering |
| 52 | Todd | Male | 2/18/1990 | 2:41 AM | 49339 | 1.695 | True | Human Resources |
| 54 | Sara | Female | 8/15/2007 | 9:23 AM | 83677 | 8.999 | False | Engineering |
| 81 | Christopher | Male | 3/30/2008 | 10:52 AM | 47369 | 14.822 | False | Legal |
| 82 | Steven | Male | 3/30/1980 | 9:20 PM | 35095 | 8.379 | True | Client Services |
| 83 | Shawn | Male | 9/23/2005 | 2:55 AM | 148115 | 6.539 | True | Finance |
| 84 | Doris | Female | 8/20/2004 | 5:51 AM | 83072 | 7.511 | False | Finance |
| 85 | Jeremy | Male | 2/1/2008 | 8:50 AM | 100238 | 3.887 | True | Client Services |
| 87 | Annie | Female | 1/30/1993 | 2:05 AM | 144887 | 8.276 | True | Sales |
| 88 | Donna | Female | 11/27/1991 | 1:59 PM | 64088 | 6.155 | True | Legal |
| 89 | Janice | Female | 3/12/2016 | 12:40 AM | 51082 | 11.955 | False | Legal |
| 92 | Linda | Female | 5/25/2000 | 5:45 PM | 119009 | 12.506 | True | Business Development |
| 94 | Harry | Male | 8/26/1981 | 3:16 PM | 130620 | 7.030 | False | Legal |
append:¶# Deprecated en versión 1.4.0
datos1.concat(datos2)
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-49-cb6596813235> in <cell line: 0>() ----> 1 datos1.concat(datos2) /usr/local/lib/python3.11/dist-packages/pandas/core/generic.py in __getattr__(self, name) 6297 ): 6298 return self[name] -> 6299 return object.__getattribute__(self, name) 6300 6301 @final AttributeError: 'DataFrame' object has no attribute 'concat'
datos = {'nombre':['María', 'Luis', 'Carmen', 'Antonio'],
'apellidos': ['López Martínez', 'Tortosa Riquelme', 'Galindo Pérez', 'Guillén Gómez'],
'edad':[21, 21, 22, 21],
'Business Intelligence': [8.1, 6.84, 5.2, 9.5],
'Web de Datos': [4.2, 7.5, 8.2, 1.3],
'Investigación y Ciencia Abierta': [6.1, 4.32, 2.41, 10]
}
df = pd.DataFrame(datos)
df
| nombre | apellidos | edad | Business Intelligence | Web de Datos | Investigación y Ciencia Abierta | |
|---|---|---|---|---|---|---|
| 0 | María | López Martínez | 21 | 8.10 | 4.2 | 6.10 |
| 1 | Luis | Tortosa Riquelme | 21 | 6.84 | 7.5 | 4.32 |
| 2 | Carmen | Galindo Pérez | 22 | 5.20 | 8.2 | 2.41 |
| 3 | Antonio | Guillén Gómez | 21 | 9.50 | 1.3 | 10.00 |
Si queremos pasar este DataFrame en formato ancho a formato largo (columnas a filas), podemos utilizar la función melt:
dfLargo = df.melt(id_vars=['nombre', 'apellidos', 'edad'], var_name='asignatura', value_name='nota')
dfLargo
| nombre | apellidos | edad | asignatura | nota | |
|---|---|---|---|---|---|
| 0 | María | López Martínez | 21 | Business Intelligence | 8.10 |
| 1 | Luis | Tortosa Riquelme | 21 | Business Intelligence | 6.84 |
| 2 | Carmen | Galindo Pérez | 22 | Business Intelligence | 5.20 |
| 3 | Antonio | Guillén Gómez | 21 | Business Intelligence | 9.50 |
| 4 | María | López Martínez | 21 | Web de Datos | 4.20 |
| 5 | Luis | Tortosa Riquelme | 21 | Web de Datos | 7.50 |
| 6 | Carmen | Galindo Pérez | 22 | Web de Datos | 8.20 |
| 7 | Antonio | Guillén Gómez | 21 | Web de Datos | 1.30 |
| 8 | María | López Martínez | 21 | Investigación y Ciencia Abierta | 6.10 |
| 9 | Luis | Tortosa Riquelme | 21 | Investigación y Ciencia Abierta | 4.32 |
| 10 | Carmen | Galindo Pérez | 22 | Investigación y Ciencia Abierta | 2.41 |
| 11 | Antonio | Guillén Gómez | 21 | Investigación y Ciencia Abierta | 10.00 |
Para pasar de formato largo a ancho, se utiliza el método pivot:
dfLargo.pivot(index=['nombre', 'apellidos', 'edad'], columns='asignatura', values='nota')
| asignatura | Business Intelligence | Investigación y Ciencia Abierta | Web de Datos | ||
|---|---|---|---|---|---|
| nombre | apellidos | edad | |||
| Antonio | Guillén Gómez | 21 | 9.50 | 10.00 | 1.3 |
| Carmen | Galindo Pérez | 22 | 5.20 | 2.41 | 8.2 |
| Luis | Tortosa Riquelme | 21 | 6.84 | 4.32 | 7.5 |
| María | López Martínez | 21 | 8.10 | 6.10 | 4.2 |
DataFrames. Uno de ellos usando un diccionario, y el otro usando una lista de listas. Después, concatena ambos DataFrames con la función concat.¶Respuesta 4:
# Responde aquí
# Responde aquí