Fastbook 07
Programación en Python
Tratamiento de datos
Edix Educación
07. Tratamiento de datos
En los dos fastbooks anteriores hemos aprendido los fundamentos de la librería
Pandas: sus principales estructuras, la series y los dataframes; así como ciertas
operaciones con dataframes (creando agrupaciones, transformándolos y
combinándolos entre sí).
El objetivo de este capítulo es profundizar en el tratamiento y limpieza de datos,
para lo que comenzaremos con los valores perdidos, viendo cómo dete ctarlos y
rellenarlos. También nos apartaremos por un momento de los campos numéricos
para ver qué son las variables categóricas, y concluiremos el tema profundizando en
las cadenas de texto.
Autor: Jesús Aguirre
Missing values
Variables categóricas y discretización
Encadenamiento de operaciones
Strings y expresiones regulares
Conclusiones
Lección 1 de 5
Missing values
Edix Educación
Hasta ahora hemos trabajado con datos completos, pero lo más frecuente es que no tengamos la
información de todos los campos para todos los registros.
Los missing values, o datos perdidos o no disponibles, son uno
de los problemas más comunes en Data Science.
En este apartado aprenderemos a trabajar con ellos, y a rellenar estos valores desconocidos a
partir de los datos que sí conocemos.
Missing values en Numpy
SI recordáis, Python dispone de un objeto None que indica la ausencia de información. No
obstante, precisamente por ser un objeto, no podemos utilizarlo en arrays numéricos de Numpy
(y por tanto, tampoco en series o columnas de un dataframe).
Como veis, al incluir un valor None en el array, se produce un casting automático a tipo object.
Por tanto, si queremos sumar los contenidos del array, obtenemos un error.
Para evitarlo, en Numpy se define un valor especial llamado NaN (not a number, valor no
numérico). Este valor, pese a su propia definición, tiene tipo float, con lo que sí podríamos usarlo
en arrays de ese tipo. Veamos un ejemplo.
Como veis, de nuevo se ha producido un casting, pero en este caso a float.
¿Podremos realizar la suma del array?
No hemos obtenido un error, pero probablemente no es el resultado que esperábamos.
Por suerte, Numpy tiene métodos equivalentes para las operaciones numéricas donde se
ignoran los NaNs.
En esta tabla tenéis listados esos métodos. Simplemente deberéis incluir nan antes del nombre
del método.
Operación Significado
Índice del valor máximo (sin incluir NaN) de los elementos del
nanargmax
array
Índice del valor mínimo (sin incluir NaN) de los elementos del
nanargmin
array
Producto acumulado (sin incluir NaN) de los elementos del
nancumprod
array
nancumsum Suma acumulada (sin incluir NaN) de los elementos del array
nanmax Máximo (sin incluir NaN) de los elementos del array
nanmean Media (sin incluir NaN) de los elementos del array
nanmedian Mediana (sin incluir NaN) de los elementos del array
nanmin Mínimo (sin incluir NaN) de los elementos del array
nanpercentile Percentil (sin incluir NaN) de los elementos del array
nanprod Producto (sin incluir NaN) de los elementos del array
nanquantile Cuantil (sin incluir NaN) de los elementos del array
nanstd Desviación típica (sin incluir NaN) de los elementos del array
nansum Suma (sin incluir NaN) de los elementos del array
nanvar Varianza (sin incluir NaN) de los elementos del array
Missing values en Pandas
Siempre decimos que Pandas se basa en Numpy, así que es de esperar un comportamiento
similar.
Creemos una serie con missing values.
En este caso, el comportamiento es ligeramente diferente: mientras que Numpy creaba un array
de tipo objeto, ya que None no es numérico, Pandas crea una serie de floats, convirtiendo el None
en NaN (aunque lo veáis con las N en mayúsculas es el valor [Link]).
Veamos ahora un dataframe con columnas de varios tipos.
Vemos que en el campo de medios y en es_online se han mantenido los valores None, y en el
numérico se ha transformado en NaN.
Además, si vemos los tipos de las columnas, es_online se ha transformado en tipo object. Esto se
debe a que no existe un valor NaN booleano, y por tanto no se puede almacenar en ese tipo.
Un dato curioso: si convertimos a booleano [Link], obtendremos True, pero si convertimos
None, obtendremos False. ¡Tened mucho cuidado forzando conversiones!
Detectando missing values en Pandas
En Pandas disponemos del método isna para detectar elemento a elemento si se trata de missing
values o NAs (tanto None como [Link] se cuentan como True). También podemos escribirlo
como isnull (es un alias para la misma función).
Si en lugar de obtener los NAs, queremos los elementos que no lo son, disponemos de la función
notna (y su alias notnull).
Como caso particular, el infinito ([Link]) no se considera como NA. Si queréis detectar qué
valores son infinitos, disponéis de la función [Link] para arrays numéricos (o que se puedan
convertir a tipo numérico).
Por último, con la función dropna podréis eliminar las filas o columnas que contengan missing
values. Con el parámetro axis indicamos si queremos eliminar filas (0) o columnas (1), y con
how si queremos eliminar las filas o columnas que tengan algún NA (valor any, opción por
defecto) o las que sean enteras NA (valor all).
Vemos que por defecto elimina las filas con algún valor NA, quedándonos solo con la primera y
la última.
También podemos especificar con el parámetro thresh un umbral mínimo de valores no NA para
mantener la fila o columna, y un subconjunto del eje a considerar mediante subset (por ejemplo,
si estamos eliminando filas, las columnas donde comprobaremos valores NA).
En este caso, exigimos que haya al menos un valor no NA en cada columna, y como eso se
cumple en todas, mantenemos el dataframe intacto.
En este último ejemplo, solo buscamos NAs en la columna booleano. Como no hay ninguno, se
mantienen todas las filas de la tabla.
Rellenando missing values en Pandas
Si una columna tiene un número bajo de missing values, suele ser más sensato rellenar esos
valores que eliminar la columna al completo. En Pandas podremos realizar esto con la función
fillna.
Podemos pasar un valor para rellenar los NAs usando el parámetro value. Puede ser tanto un
único valor, como un diccionario donde se indique para cada columna (claves) cuál será el valor
de relleno (valores). También podemos usar una serie o un dataframe, aunque es menos común.
En el caso anterior hemos rellenado a 0 todas las columnas, pero podemos rellenar con
diferentes valores en cada una.
También es muy frecuente usar el parámetro method para indicar el método a usar para rellenar
los missing values. Podemos elegir dos: ll (forward fill, relleno hacia adelante) propagará el
último dato válido, mientras que bfill (backwards fill, relleno hacia atrás) utilizará el siguiente
dato válido para rellenar el actual.
El parámetro method es especialmente útil para rellenar valores en series temporales
(sucesiones de datos en una escala temporal, las veremos en profundidad en el siguiente
fastbook).
En este caso tenemos valores ordenados temporalmente, con lo que al utilizar el método ll,
arrastramos el último valor no nulo, asumiendo que se mantiene en el tiempo.
También disponemos del parámetro axis para elegir si queremos rellenar a lo largo de filas
(eje 0, el valor por defecto), o columnas (eje 1).
En el ejemplo, usamos un relleno bfill, es decir, propagamos hacia atrás el último valor válido,
y a lo largo de las columnas. Por tanto, nuestros NAs en las tres primeras columnas se van a
rellenar con el valor True correspondiente a la última.
Por último, veamos el parámetro limit, que especifica el número máximo de missing values
consecutivos que podremos rellenar (por defecto no tenemos máximo).
Como veis, solo hemos rellenado valores en la segunda fila, ya que nuestro límite de missing
values rellenados de forma consecutiva era 1.
También podemos utilizar un valor promedio para rellenar datos desconocidos.
Volviendo a nuestro ejemplo de productos, creemos algunos valores perdidos para
rellenarlos.
Una opción sencilla para rellenar el dato de semanas de histórico es utilizar la media del resto
de productos. Simplemente la calculamos, y utilizamos fillna para colocarla en las filas sin
dato.
Por supuesto, podemos afinar todo lo que queramos, utilizando la media por grupos, o
incluso por tramos de ventas.
Missing values en funciones de Pandas
Además de las funciones anteriores para rellenar missing values, hay muchas más funciones que
nos permiten tratar este tipo de datos mediante parámetros.
Por ejemplo, en read_csv tenemos tres parámetros relacionados con valores NA:
na_values: para indicar qué cadenas queremos reconocer como missing values (por
defecto ya aparecen muchas como NA, NULL, NaN, nan o N/A).
keep_default_na: para mantener, o no, esas cadenas que se consideran missing
values por defecto.
na_filter: para eliminar la detección de missing values y ganar eficiencia en la lectura,
pero solo si estamos seguros de que no hay ninguno.
Otra función muy utilizada, y que vimos en fastbooks anteriores, es value_counts, que nos
permite contar el número de ocurrencias de un valor en una serie. Por defecto, no incluirá los
valores perdidos o missing, pero podemos cambiar este comportamiento mediante el parámetro
dropna.
Y, para concluir con estos ejemplos, recordemos la función pivot_table que vimos en el fastbook
anterior. En el caso de que alguno de los elementos de la tabla pivotada quedara sin valor,
podemos rellenarlo mediante el parámetro fill_value.
Lección 2 de 5
Variables categóricas y discretización
Edix Educación
En este apartado veremos cómo trabajar con variables categóricas, y a discretizar variables
continuas en tramos.
Variables categóricas
A lo largo de los dos últimos fastbooks hemos tratado el dataframe de productos que incluía un
campo con 5 valores distintos.
Ese campo es de tipo string (cadena de caracteres), pero Pandas nos permite usar las variables
categóricas ([Link]) para trabajar con tipos de variables con un número limitado de
posibles valores.
Algunas de las ventajas que nos ofrecen estas variables son las siguientes:
Optimizar la memoria utilizada: ya que solo admitimos un conjunto limitado de
posibles valores, la memoria requerida para almacenar una variable categórica será
menor que para un string (al igual que es menor para un booleano que para un
entero).
Incluir orden en la variable: en los strings, el orden subyacente es el lexicográfico
(alfabético), con lo que, si tenemos una variable con los valores ‘bajo’, ‘medio’ y
‘alto’, no se corresponderá con el orden esperado. En una variable categórica
podemos indicar el orden entre las distintas categorías (si aplica).
Indicar el tipo de la variable a otras librerías: al utilizar variables categóricas, se
tratarán como tal a la hora de realizar gráficos o modelos (en lugar de tratarse como
strings).
1 Creación
Para crear una variable categórica, simplemente usaremos el constructor [Link].
Automáticamente, asumirá que las categorías son los valores únicos del array, pero podemos
indicarlas mediante el parámetro categories.
Como veis, al indicar solamente dos de las 5 categorías, obtenemos valores NaN. Los valores
posibles de una variable categórica son únicamente las categorías y el valor NaN.
También podemos crear variables categóricas ordenadas mediante el parámetro ordered.
Como no tiene mucho sentido ordenar tipos de producto, recuperaremos la variable
tipo_precio que creamos en el fastbook 05.
Accediendo a esta variable, vemos que aparece el orden que hemos indicado.
Por último, también podemos convertir una columna en categórica utilizando el método
astype.
Mediante los atributos categories y codes podemos acceder respectivamente a las diferentes
categorías, y a los valores de la variable codificados como enteros.
Si queremos acceder a ellos en una serie de un dataframe, utilizaremos el atributo cat (al igual
que posteriormente usaremos str para los métodos vectorizados de las columnas de tipo
string).
2 Métodos de las variables categóricas
Las variables categóricas disponen de una serie de métodos que nos ayudarán a manejar el
conjunto de categorías y su orden.
Método Significado
add_categories Añade nuevas categorías a las ya existentes
Elimina categorías, pasando los valores
remove_categories
correspondientes a NaN
Elimina las categorías que no aparezcan en los
remove_unused_categories
valores
set_categories Establece las nuevas categorías de la variable
Renombra las categorías con las nuevas
rename_categories
proporcionadas
Reordena las categorías, permitiendo añadir orden si
reorder_categories
no existía
as_ordered Transforma las categorías en categorías ordenadas
as_unordered Elimina el orden de las categorías
Como siempre, veamos algún ejemplo para entender estas funciones.
Comencemos por crear una serie categórica.
Si añadimos una categoría, pasamos a tener 6 categorías.
También podemos renombrar una de las categorías, con lo que se cambiarán todos los
valores de esa categoría.
Por último, probemos a reordenar nuestros tipos de productos, induciendo, además, un
orden entre categorías.
3 Transformación a variables numéricas
Tal y como veíamos en los apartados anteriores, las variables categóricas aparecen
representadas internamente por valores numéricos (el atributo codes). Esta transformación
puede ser suficiente para las variables categóricas ordenadas, ya que el orden se refleja también
en la variable numérica. No obstante, en las categorías sin orden asociado, utilizar esa variable
numérica pierde el sentido lógico, ya que el orden que tiene es aleatorio.
Por tanto, a la hora de realizar modelos, es frecuente convertir las variables categóricas a lo que
se denomina one-hot encoding.
Este tipo de codi cación crea variables binarias para cada categoría,
donde se marca con un 1 si el valor de la variable categórica original
coincide con esa categoría; y con un 0 en caso contrario.
Para realizar esta transformación en Pandas, podéis utilizar la función get_dummies.
Con el parámetro columns podéis indicar sobre qué columnas aplicar la transformación, y con
drop_first podéis eliminar una columna, ya que podemos inferir que, si el resto de las columnas
tienen valor 0, esa observación pertenecerá a la categoría faltante (y en la fase de modelización
no nos interesará tener información redundante).
Discretización de variables
Al trabajar con datos, es muy frecuente querer transformar variables continuas (como los
precios o las ventas de nuestros ejemplos anteriores) en grupos, ya sea para realizar análisis
exploratorio en base a ellos, o para simplificar la información. A este proceso le llamaremos
discretización.
En Pandas podemos utilizar las funciones qcut y cut para
realizar estas discretizaciones.
1 Discretización en cuantiles
La función qcut transformará un array o serie en cuantiles (los indicaremos con el parámetro q).
Por ejemplo, con q = 4 obtendremos cuartiles (4 intervalos), mientras que con q = 10, el resultado
serán deciles.
Con el parámetro labels podemos indicar etiquetas para las discretizaciones, en lugar de que nos
aparezca el intervalo.
Con retbins obtendremos una tupla con, además de las discretizaciones, un array con los puntos
de corte.
2 Discretización en intervalos fijos.
Aunque cortar en cuantiles es cómodo, muchas veces tiene más sentido hacer los cortes en base
a umbrales absolutos. Para ello, utilizaremos la función cut de Pandas.
Su funcionamiento es muy similar a qcut, salvo que deberemos sustituir el número de cuantiles
por los umbrales (parámetro bins). Podemos introducir simplemente el número de umbrales,
con lo que obtendremos intervalos de la misma amplitud.
Y también indicar los intervalos exactos mediante una lista de umbrales. Al igual que en qcut,
disponemos del parámetro labels para asignar etiquetas en lugar del intervalo.
Además, como en cut estamos clasificando los valores según estén incluidos en los intervalos
marcados por los umbrales, podremos elegir si estos intervalos incluyen el extremo derecho o
no (con el parámetro right, que por defecto es True). Esto se veía en el primer ejemplo, donde el
paréntesis (abierto) indica que el extremo no está incluido, y el corchete (cerrado), que sí se
incluye en el intervalo.
De igual manera, podemos indicar que se incluya el primer extremo inferior, utilizando el
parámetro include_lowest (por defecto, a False).
Lección 3 de 5
Encadenamiento de operaciones
Edix Educación
A lo largo de los últimos capítulos hemos visto cómo encadenar varias operaciones sobre
dataframes utilizando métodos separados por saltos de línea.
Recordad que, aunque en la mayoría de los ejemplos que hemos visto hemos encadenado
operaciones mediante el carácter de salto de línea \, la forma ‘purista’ de hacerlo
(recomendada por la guía de estilo de Python) es encapsulando la operación entre paréntesis,
con lo que este carácter ya no será necesario.
Como ya vimos en el fastbook anterior, podemos utilizar el método merge del dataframe, o la
función equivalente [Link]. No obstante, al usar el método del dataframe, estamos
encadenando la operación, utilizando lo que se llama una alternativa funcional a la función
[Link], que recibe ambos dataframes por parámetro.
Otro ejemplo de alternativa funcional es el método assign. También nos permite seguir
encadenando funciones, mientras que si usáramos la asignación mediante corchetes (no
funcional), deberíamos romper la cadena.
Para ayudarnos a seguir encadenando operaciones, Pandas dispone del método pipe, con el que
podremos utilizar funciones definidas por nosotros mismos.
Partiendo del ejemplo anterior, podemos crear una función que elimine la columna de
provincias y cree la variable de ventas por tienda.
En un enfoque no funcional, utilizaremos [Link] para cruzar las dos tablas, y lo
introduciremos como parámetro de nuestra nueva función.
No obstante, utilizando pipe, podemos escribir este mismo código de forma funcional,
mucho más cómoda tanto para pensar como para leer el código posteriormente.
Por supuesto, utilizar un enfoque más o menos funcional es una cuestión de gustos y
preferencias de cada uno. Habrá ocasiones en las que merezca la pena romper la cadena por
claridad, o por rendimiento (por ejemplo, para dataframes muy grandes, la asignación con
corchete será algo más rápida que con el método assign).
Personalmente, encuentro más cómoda la programación
funcional, ya que además se asemeja mucho al estilo tidyverse
en R, y esa es la razón por la que la mayoría del código de
estos fastbooks está escrito con ese enfoque.
Lección 4 de 5
Strings y expresiones regulares
Edix Educación
A lo largo de estos fastbooks nos hemos centrado mucho en las operaciones sobre campos
numéricos, pero los textos también tienen una importancia capital en el mundo de Data
Analytics. Muchas veces contienen errores que querremos subsanar, o querremos realizar
operaciones sobre ellos para crear nuevas variables.
Métodos propios de los strings
Cuando en el primer fastbook introdujimos los strings, vimos sus características básicas y cómo
hacer indexaciones sobre ellos, pero apenas profundizamos en la gran variedad de métodos que
tienen los objetos de tipo str.
Reemplazar caracteres
–
Probablemente uno de los métodos para strings más utilizados es replace. Esta función nos
permitirá reemplazar todas las ocurrencias de la cadena old por la cadena new (sus dos primeros
parámetros). También podemos limitar el número de veces que realizaremos la operación
mediante el parámetro count (por defecto, sustituiremos todas las ocurrencias).
Separación
–
Con el método split podemos separar una cadena de texto en varias. Su primer (y más
importante) parámetro es el separador (sep) que delimitará los fragmentos dentro de la cadena.
Además, con el parámetro maxplit podemos indicar el número máximo de fragmentos que
queremos hacer.
En el ejemplo, partimos el string en distintos medios, usando como delimitador la coma seguida
de espacio. Al indicar que solo queremos 2 fragmentos, obtenemos una lista con esos dos
primeros medios, y el resto de la cadena sin separar.
Mayúsculas y minúsculas
–
Una serie de métodos muy útiles para limpiar y formatear a nuestro gusto cadenas de caracteres
son upper, lower, capitalize, title y swapcase.
Operación Significado Ejemplo Resultado
Devuelve una
cadena donde todas
upper "Cadena".upper() 'CADENA'
las letras son
mayúsculas
lower Devuelve una "Cadena".lower() 'cadena'
cadena donde todas
las letras son
minúscula
Devuelve una
'Cadena con
cadena donde la "cadena con
capitalize palabras'
primera letra es palabras".capitalize()
mayúscula
Devuelve una
cadena donde la 'Cadena Con
"cadena con
title primera letra de Palabras'
palabras".title()
cada palabra es
mayúscula
Transforma las
mayúsculas en 'CADENA'
swapcase "Cadena".swapcase()
minúsculas y
viceversa
Comienzos y nales
–
Los métodos startswith y endswith nos permiten averiguar si una cadena comienza o finaliza con
una subcadena.
Tipos de caracteres
–
Por último, tenemos una serie de métodos que nos ayudarán a determinar qué tipo de caracteres
hay en la cadena.
Operación Significado
isalnum Detecta si la cadena es alfanumérica
isalpha Detecta si la cadena es alfabética
isnumeric Detecta si la cadena es numérica
islower Detecta si la cadena está formada por letras minúsculas
isupper Detecta si la cadena está formada por letras mayúsculas
Veamos algunos ejemplos de estos últimos métodos.
La cadena medios no es alfanumérica, ya que contiene comas.
No obstante, si la partimos como en el ejemplo de split, las cuatro cadenas resultantes sí que
son alfanuméricas.
La cadena "100" es numérica, ya que solo está compuesta por dígitos.
Como veremos a continuación, todos estos métodos serán
particularmente útiles en dataframes, donde podremos
indicar asignaciones condicionales en base al resultado de su
ejecución sobre una columna.
Métodos para columnas de texto en Pandas
Aunque podríamos aplicar estos métodos sobre una columna (una serie) de un dataframe
utilizando apply, es mucho más cómodo acceder a los métodos de los strings mediante el
atributo str.
De esta forma, podemos utilizar todos los métodos del apartado anterior, de forma más eficiente
y con un correcto tratamiento de valores nulos.
Si os fijáis, hemos introducido un NaN en la primera fila, y el cambio a mayúsculas se ha
realizado sin problemas en el resto.
Si lo intentamos realizar con un apply, obtendremos un error de tipos, ya que no admite valores
nulos.
Además de los métodos que ya hemos visto, tenemos disponibles varios más. En la siguiente
tabla tenéis algunos de ellos, y nos reservamos los relacionados con búsqueda y
reemplazamiento para el siguiente apartado: expresiones regulares.
Función Significado
get Extrae elementos en la posición especificada
Realiza el slice del string marcado por los parámetros start,
slice
stop y step
slice_replace Reemplaza el slice con otro valor, indicado en el parámetro repl
Duplica cada string en la serie. Se puede indicar el número de
repeat
repeticiones con el parámetro repeats
Ajusta el string a una longitud mínima fija, marcada por width.
pad Podemos indicar el lado por el que se rellenará con side (‘left’,
‘right’ o ‘both’), y el carácter con fillchar.
Elimina caracteres en blanco (espacios, tabuladores y saltos de
strip
línea)
cat Concatena strings mediante un separador dado
join Concatena listas de strings mediante un separador dado
Veamos algún ejemplo de estas funciones.
Con get obtenemos la inicial de cada tipo, accediendo al índice 0.
Con pad podemos rellenar de ceros el id_producto, para lo que primero tendremos que
convertirlo a tipo string.
Y, por último, combinemos esta columna con la de tipo usando la función cat.
Expresiones regulares
Las expresiones regulares son secuencias de caracteres que conforman
patrones de búsqueda.
Por tanto, son más complejas que una secuencia común, pero a cambio son mucho más
potentes.
Comencemos con lo básico. Además de los caracteres a los que ya estamos habituados
(alfanuméricos, guiones, llaves, etc.), las expresiones regulares incluyen metacaracteres, que
indican tipos de caracteres o agrupaciones.
Algunos de los metacaracteres vienen precedidos por la barra inversa, \.
Metacarácter Significado
\d Dígito
\D No dígito
\w Palabra
\W No palabra
\s Espacio
\S No espacio
Es decir, el metacarácter \d indica un dígito, como por ejemplo, 1 o 7.
Además, existen otros metacaracteres que nos permiten indicar el número de repeticiones, o
dónde debe estar la subcadena, entre otras opciones. Son los que podéis ver en la siguiente tabla.
(En los ejemplos de comienzo y final de la cadena, se ha limitado la expresión regular para no
complejizar los ejemplos con otros metacaracteres. Las expresiones completas para reconocer
la cadena ''hola mundo'' completa serían ''^hola.*'' y ''.*mundo$'', respectivamente).
Expresión Cadena
Metacarácter Significado
regular detectable
[] Conjunto de caracteres ''[a-z]'' ''e''
. Cualquier carácter ''ca.a'' ''casa''
''hola
^ Comienzo de la cadena ''^hola''
mundo''
''hola
$ Final de la cadena ''mundo$''
mundo''
* Cero o más ocurrencias ''\d'' ''3''
+ Una o más ocurrencias '' \d+' ''360''
? Cero o una ocurrencia '' \d?' ''3''
Número concreto de
{} ''\d{2}'' ''33''
ocurrencias
| Or lógico ''hola|buenas'' ''hola''
Escapa otros
metacaracteres, es decir
\ ''\.'' ''.''
permite capturar el carácter
literal que representan
Captura y agrupa una
()
cadena
A continuación veremos ejemplos de estos metacaracteres, utilizando funciones de Python.
1 Expresiones regulares en Python
En Python, podemos utilizar el módulo re para tratar con expresiones regulares. Además, y como
veremos posteriormente, hay varias funciones de Pandas que también admitirán este tipo de
secuencias.
Búsqueda
Para buscar todas las ocurrencias de un patrón en un string, utilizaremos la función findall.
En ella, indicaremos en primer lugar el patrón que estamos buscando (parámetro pattern) y,
en segundo lugar, la cadena sobre la que queremos buscarlo (string).
También podemos usar las funciones search y match para realizar búsquedas.
La función search busca el patron a lo largo de la cadena, devolviendo un objeto Match, o
None si no encuentra ningún resultado.
La función match busca el patrón desde el comienzo de la cadena, y devuelve un objeto
Match, o None si no encuentra resultados.
Veamos un ejemplo donde se vean las diferencias entre las tres funciones.
Al buscar todas las ocurrencias de las letras desde la ‘a’ hasta la ‘d’ en la cadena anterior,
obtenemos una lista de 10 letras. Como la cadena comienza con una ‘S’ mayúscula, match nos
devuelve None. Por último, search devuelve un objeto Match con la primera ocurrencia, la letra
‘d’.
Reemplazamiento
Para reemplazar patrones disponemos de la función sub. En este caso, después del patrón
deberemos indicar por qué queremos reemplazarlo, y ya como tercer parámetro, la cadena.
En el ejemplo hemos indicado que se reemplace cl, seguido opcionalmente por un punto
(como el punto es un metacarácter, tenemos que utilizar la barra inversa \ para poder acceder
al carácter .). El símbolo de interrogación indica que el punto puede o no aparecer, y el
símbolo del dólar indica que el patrón debe encontrarse al final de la cadena. Como la
descripción del artículo termina en cl., que encaja con el patrón, se reemplaza por la cadena
centilitros.
Partición
Si queremos partir una cadena en una lista de cadenas utilizando una expresión regular como
separador, podemos usar la función split.
En el ejemplo veis que, aunque hay varios espacios y un separador en la descripción del
artículo, se han eliminado todos al partir la cadena. Con \s indicamos que queremos separar
por espacios (donde se incluyen los tabuladores), y el + representa que debe haber 1 o más
espacios para separar.
Reutilización de expresiones regulares
Si queremos optimizar al máximo nuestro código, podemos compilar una expresión regular
y grandes
para podervolúmenes de datos.
así reutilizarla Para veces,
múltiples hacer esto, utilizaremos
algo muy útil en ella función
caso compile. complejas
de expresiones
Una vez que tenemos la expresión regular compilada, podemos aplicar sobre este objeto
cualquiera de las funciones anteriores, por ejemplo, split.
Y sobre el mismo objeto, podemos continuar aplicando más operaciones de expresiones
regulares.
3 Expresiones regulares en Pandas
Ya hemos aprendido a utilizar la librería re para tratar cadenas mediante expresiones regulares,
pero como hemos visto durante los últimos fastbooks, gran parte de nuestro tiempo como
analistas de datos en Python lo pasaremos trabajando con dataframes de Pandas.
Para ello, algunas de las funciones de tratamiento de texto de Pandas nos ofrecen la posibilidad
de utilizar expresiones regulares. Aunque la mayoría ya las hemos visto, las tenéis listadas a
continuación.
Función Significado
count Cuenta las ocurrencias de un patrón en cada elemento de la serie
replace Sustituye las ocurrencias de un patrón en cada elemento de la serie
contains Comprueba si un patrón está contenido en cada elemento de la serie
Extrae los grupos capturados por el patrón en cada elemento de la
serie.
extract
En cada elemento, se extrae el grupo sobre la primera coincidencia
del patrón
Encuentra todas las ocurrencias de un patrón en cada elemento de la
findall
serie
match Determina si un patrón aparece en cada elemento de la serie
split Divide cada elemento de la serie utilizando un patrón
Y, como siempre, veamos en algunos ejemplos cómo poner en práctica lo aprendido. A lo largo
de los ejemplos veréis como las expresiones regulares van precedidas de r, que indica que son,
precisamente, regular expressions.
Comencemos cargando un dataframe con descripciones de productos.
Ahora que ya tenemos una columna de tipo string (nombre), probemos las funciones de la
tabla anterior.
En este primer ejemplo, utilizamos count para contar cuántos números aparecen en la
descripción del producto. Con \d indicamos un dígito numérico, y con +, que aparezca una o
más veces consecutivas.
Ahora, utilizamos extract para capturar el mismo patrón del ejemplo anterior.
En este caso, tenemos que encapsular el patrón entre paréntesis para indicar que se trata de
un grupo de captura. Además, si hubiera varios números en la descripción, extract obtendrá el
primero de ellos.
Con contains comprobamos si las descripciones incluyen las subcadenas “gr” o “cl”,
seguidas opcionalmente de un punto, tras lo que finaliza la descripción.
Además de estos métodos, que son los propios de las columnas de tipo texto, podemos
utilizar expresiones regulares en más situaciones. Por ejemplo, para seleccionar columnas de
un dataframe mediante el método filter.
En el ejemplo, nos quedamos con las columnas que tienen el carácter _ y acaban en vocal.
Con esto concluimos las expresiones regulares. Como ya habéis visto, pueden complicarse
mucho, y que nos sea difícil construir la expresión regular que queramos. Para ayudaros a ello,
podéis usar páginas como [Link], que os servirán para testear expresiones regulares, y
aprender más sobre ellas.
Lección 5 de 5
Conclusiones
Edix Educación
En este fastbook hemos continuado nuestro camino de aprendizaje en Pandas. Ahora ya somos
capaces de detectar y rellenar missing values en nuestros dataframes y series. También hemos
aprendido sobre variables categóricas, y cómo obtenerlas a partir de variables numéricas
continuas.
Finalmente nos hemos detenido en el tratamiento de las cadenas de texto, aprendiendo nuevas
funciones tanto de Python puro como de Pandas, y finalizando con una de las herramientas más
útiles y difíciles que hemos visto hasta el momento: las expresiones regulares, que nos servirán
para detectar y modificar patrones de texto.
En el siguiente fastbook aprenderemos a trabajar con fechas en Python, e introduciremos las
series temporales: sucesiones de datos a lo largo de una escala temporal.
Como siempre, repasad los conceptos que hemos aprendido
en este fastbook antes de continuar con el siguiente.
¡E n h o r a b u e n a ! Fa s t b o o k s u pe r a d o
Creamos Digital Workers