Hola, me llamo Luis y en esta ocasión les traigo otro nuevo artículo.
Índice
Mientras trabajaba en un proyecto recientemente, tuve que trabajar con datos de series de tiempo distribuidos durante un año.
Quería agregar columnas para saber si una fecha específica era un feriado, así como también quería contar el número de días desde el feriado anterior y los días hasta el próximo feriado.
Como alguien relativamente nuevo en Python, fue un desafío. Sin embargo, después de investigar un poco en línea, descubrí que es bastante simple y decidí compartirlo. Estos son los objetivos de este artículo:
- Comprueba si un día es festivo o no.
- Calcule los días de las vacaciones anteriores.
- Calcule los días que faltan para las próximas vacaciones.
La puesta en marcha
Trabajaremos con el marco de datos de pandas. Por eso importamos pandas:
import pandas as pd
Ahora creemos un marco de datos que contenga fechas durante un período de un año, digamos desde el 1 de enero de 2019 hasta el 31 de diciembre de 2019. A nuestro marco de datos lo llamaremos «rango». Pandas hace que sea muy fácil generar un rango de fechas.
dates = pd.DataFrame('date':pd.date_range('2019-01-01', '2019-12-31'))
Sin embargo, debemos agregar el primer día de 2020 a este rango. La razón es que uno de nuestros objetivos es calcular los días para las próximas vacaciones.
Esto se complica en diciembre, ya que después del 25, el próximo feriado es el 1 de enero, que no se incluirá en nuestro rango de fechas, por lo tanto, lo agregamos a nuestro rango de fechas.
dates = pd.DataFrame('date':pd.date_range('2019-01-01', '2020-01-01'))
Echemos un vistazo al marco de datos que creamos:
Todas las vacaciones que puedo tener
Pandas viene con un módulo integrado que contiene los feriados federales de EE. UU. Vamos a importar eso:
from pandas.tseries.holiday import USFederalHolidayCalendar as calendar
Podemos pasar un rango de fechas a este módulo y devolverá todos los días festivos en ese rango.
cal = calendar() holidays = cal.holidays(start=dates[‘date’].min(), end=dates[‘date’].max())
En el código anterior, el módulo necesita una fecha de inicio y una fecha de finalización. En lugar de darle las fechas manualmente, podemos hacerlo de forma dinámica , lo que será útil cuando su archivo de datos cambie continuamente y se agreguen datos de forma continua.
«Vacaciones» es ahora una serie de pandas que contiene todas las fechas que son feriados federales de EE. UU.
Vacaciones o no vacaciones
Digamos que queremos una columna titulada «feriado» en nuestro marco de datos que contenga Verdadero si la fecha es un feriado federal de EE. UU. Y Falso si no lo es.
dates[‘holiday’] = dates[‘date’].isin(holidays)
Echemos un vistazo a nuestro marco de datos.
Días desde la festividad anterior y hasta la siguiente
También queríamos una columna que mostrara la cantidad de días desde el feriado anterior, así como otra que mostrara los días hasta el siguiente. Escribiremos una función para cada uno.
def days_prev_holiday(date, holidays): difference=[] for item in holidays: difference.append(int(str((item-date).days))) return abs(max([x for x in difference if x<=0]))
Analicemos el código. Lo que estamos haciendo es crear una lista de números, cada número representa el número de días desde un feriado determinado. Dado que la fecha ha pasado, restar la fecha actual de la fecha pasada nos dará un número negativo.
Para determinar los días a partir del feriado pasado más cercano, devolvemos el número máximo entre todos los números negativos. Dado que estamos viendo el número de días, no necesitamos el signo “-”
, por lo tanto, usamos abs (número) para eliminar el signo menos.
Esta función se puede reescribir en líneas menores usando la comprensión de listas; sin embargo, para facilitar la lectura, mantendremos nuestro bucle for.
Ahora, para calcular el número de días hasta las próximas vacaciones, usamos prácticamente la misma lógica, sin embargo, esta vez devolvemos la cantidad mínima de todos los números mayores que 0
. Por lo tanto, la función se convierte en:
def days_next_holiday(date, holidays): difference=[] for item in holidays: difference.append(int(str((item-date).days))) return min([x for x in difference if x>=0])
Ahora que tenemos nuestras funciones escritas, podemos aplicarlas a todas las filas en la columna correspondiente en nuestro marco de datos.
dates['days_previous_holiday']= dates.apply(lambda row: days_prev_holiday(row['date'], holidays), axis=1) dates['days_next_holiday']= dates.apply(lambda row: days_next_holiday(row['date'], holidays), axis=1)
Echemos un vistazo final al marco de datos que creamos:
Espero que te haya sido de utilidad. Gracias por leer este post.
Añadir comentario