es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La función Transformer de Pandas genera una advertencia de “SettingWithCopy”.

Estoy aprendiendo a usar pipelines y he creado un pipeline bastante simple con un FunctionTransformer para agregar una nueva columna, un ordinal encoder y un modelo LinearRegression.

Pero resulta que estoy obteniendo un error de SettingwithCopy cuando ejecuto el pipeline, y he identificado que el problema está en el FunctionTransformer.

Aquí está el código, he omitido todo el código innecesario (como el ordinal encoder y el regressor en el pipeline) –

def weekfunc(df):
    df['date'] = pd.to_datetime(df.loc[:,'date'])
    df['weekend'] = df.loc[:, 'date'].dt.weekday
    df['weekend'].replace(range(5), 0, inplace = True)
    df['weekend'].replace([5,6], 1, inplace = True)
    return df

get_weekend = FunctionTransformer(weekfunc)

pipe = Pipeline([
    ('weekend transform', get_weekend),
])

pipe.transform(X_train)

Esto me da el siguiente error –

/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:12: SettingWithCopyWarning: 
Se está intentando establecer un valor en una copia de una rebanada de un DataFrame.
Intenta usar .loc[row_indexer,col_indexer] = value en su lugar

Consulta las advertencias en la documentación: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  if sys.path[0] == '':
/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:13: SettingWithCopyWarning: 
Se está intentando establecer un valor en una copia de una rebanada de un DataFrame.
Intenta usar .loc[row_indexer,col_indexer] = value en su lugar

Consulta las advertencias en la documentación: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  del sys.path[0]
/opt/conda/lib/python3.7/site-packages/pandas/core/generic.py:6619: SettingWithCopyWarning: 
Se está intentando establecer un valor en una copia de una rebanada de un DataFrame

Consulta las advertencias en la documentación: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  return self._update_inplace(result)

Esto es extraño ya que puedo realizar lo mismo sin el FunctionTransformer y no obtener el error.

Realmente estoy confundido aquí, así que cualquier ayuda es apreciada.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema aquí está relacionado con la forma en que pandas maneja el indexación anidada, lo que significa que cuando se realizan múltiples operaciones de indexación en un dataframe, pandas puede devolver una vista del dataframe original o una nueva copia, dependiendo de la situación.

    En este caso particular, la función “weekfunc” intenta modificar una sección del dataframe original “df” utilizando indexación anidada, lo cual no se recomienda ya que puede llevar a un comportamiento inesperado o errores.

    Para evitar el mensaje de advertencia “SettingWithCopyWarning”, puedes modificar la función “weekfunc” para utilizar la indexación “.loc” en su lugar, que es la forma recomendada de modificar datos en pandas. Aquí tienes una versión actualizada de la función:

    def semana_func(df):
        df = df.copy()  # crea una copia del dataframe original
        df.loc[:, 'date'] = pd.to_datetime(df.loc[:, 'date'])
        df.loc[:, 'weekend'] = df.loc[:, 'date'].dt.weekday
        df.loc[:, 'weekend'].replace(range(5), 0, inplace=True)
        df.loc[:, 'weekend'].replace([5,6], 1, inplace=True)
        return df
    

    El método copy() crea una nueva copia del dataframe original, por lo que cualquier modificación realizada en la copia no afectará al dataframe original. La indexación .loc se utiliza para modificar los datos en su lugar, lo cual debería evitar el mensaje de advertencia “SettingWithCopyWarning”.

    Con esta función actualizada, puedes utilizar FunctionTransformer en tu pipeline sin recibir la advertencia:

    obtener_fin_semana = FunctionTransformer(semana_func)
    
    pipe = Pipeline([
        ('transformación fin de semana', obtener_fin_semana),
    ])
    
    pipe.transform(X_train)
    

Comments are closed.