Quiero calcular la semana del mes para una fecha específica. Para calcular la semana del mes, actualmente utilizo la función definida por el usuario.

Marco de datos de entrada:

Input data frame

Marco de datos de salida:

Output dataframe

Esto es lo que he intentado:

from math import ceil
def week_of_month(dt):
    """ 
       Returns the week of the month for the specified date.
    """

    first_day = dt.replace(day=1)

    dom = dt.day
    adjusted_dom = dom + first_day.weekday()

    return int(ceil(adjusted_dom/7.0))

Después de este,

import pandas as pd

df = pd.read_csv("input_dataframe.csv")
df.date = pd.to_datetime(df.date)
df['year_of_date'] = df.date.dt.year
df['month_of_date'] = df.date.dt.month
df['day_of_date'] = df.date.dt.day


wom = pd.Series()

# worker function for creating week of month series
def convert_date(t):
    global wom
    wom = wom.append(pd.Series(week_of_month(datetime.datetime(t[0],t[1],t[2]))), ignore_index = True)

# calling worker function for each row of dataframe
_ = df[['year_of_date','month_of_date','day_of_date']].apply(convert_date, axis = 1)

# adding new computed column to dataframe
df['week_of_month'] = wom
# here this updated dataframe should look like Output data frame.

Lo que esto hace es para cada fila de marco de datos que calcula la semana del mes usando la función dada. Hace que los cálculos sean más lentos a medida que el marco de datos crece a más filas. Porque actualmente tengo más de 10M + filas.

Estoy buscando una forma más rápida de hacer esto. ¿Qué cambios puedo hacer a este código para vectorizar esta operación en todas las filas?

Gracias de antemano.

Editar: lo que funcionó para mí después de leer las respuestas está debajo del código,

first_day_of_month = pd.to_datetime(df.date.values.astype('datetime64[M]'))
df['week_of_month'] = np.ceil((df.date.dt.day + first_day_of_month.weekday) / 7.0).astype(int)
0
Parth 16 oct. 2018 a las 14:51

2 respuestas

La mejor respuesta

El método week_of_month se puede vectorizar. Podría ser beneficioso no realizar la conversión a objetos de fecha y hora y, en su lugar, utilizar solo métodos de pandas.

first_day_of_month = df.date.to_period("M").to_timestamp()
df["week_of_month"] = np.ceil((data.day + first_day_of_month.weekday) / 7.0).astype(int)
1
w-m 16 oct. 2018 a las 12:30

Desde el principio sin siquiera entrar en su código y mencionar problemas X / Y, etc .:
Intente obtener una lista de fechas únicas, estoy seguro de que en las filas de 10 millones tiene más de una es un duplicado.

Pasos:

  1. cree un segundo df que contenga solo las columnas que necesita y no duplicados (drop_duplicates)
  2. ejecuta tu función en el marco de datos pequeño
  3. Fusionar las dfs grandes y pequeñas
  4. (Opcional) Suelta la pequeña
0
nailimp 16 oct. 2018 a las 12:17