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.

pandas numpy: cómo simplificar múltiples parámetros de funciones vectorizadas

Tengo un df, lo puedes obtener al ejecutar este código:

import numpy as np
import pandas as pd
from io import StringIO
dfs = """
    M0     M1   M2  M3 M4   M5 age
1   1      2    3    4  5    6  3.2        
2   7      5    4    5  8    3  4.5
3   4      8    9    3  5    2  6.7
"""
df = pd.read_csv(StringIO(dfs.strip()), sep='\s+', )

Y en base a la lógica del negocio, tengo la siguiente función, la salida también es lo que esperaba:

def func(M0,M1,M2,M3,M4,M5,age):
    newcol=np.prod([M0,M1,M2,M3,M4,M5][0:age])
    return newcol

vfunc = np.frompyfunc(func, 7, 1)
df['newcol']=vfunc(df['M0'].values,df['M1'].values,df['M2'].values,df['M3'].values,df['M4'].values,df['M5'].values,df['age'].values.astype(int))

df

La salida es:

M0  M1  M2  M3  M4  M5  age newcol
1   1   2   3   4   5   6   3.2 6
2   7   5   4   5   8   3   4.5 700
3   4   8   9   3   5   2   6.7 8640

El problema es que hay demasiados parámetros en def func(M0,M1,M2,M3,M4,M5,age), ¿hay alguna manera de hacer que estos parámetros sean una lista o algo más para que la función sea más limpia?

Intenté lo siguiente:

def func(df):
    newcol=np.prod([df['M0'].values,df['M1'].values,df['M2'].values,df['M3'].values,df['M4'].values,df['M5'].values][0:df['age'].values.astype(int)])
    return newcol

vfunc = np.frompyfunc(func,1, 1)
df['newcol']=vfunc(df)

Pero tengo un error:

TypeError: 'float' object is not subscriptable

Observar la razón por la que no utilizo pd.apply(), es porque en mi negocio real, los datos son muy grandes y pd.apply() se ejecuta muy lentamente.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Sí, puedes crear una lista o un arreglo de numpy a partir de los valores de entrada y pasarlos como un solo argumento a la función. Aquí hay un ejemplo:

    def func(row):
        vals = np.array(row[:-1], dtype='int')  # Extrae todas las columnas excepto la última
        age = int(row[-1])  # Extrae la columna de edad y convierte a entero
        newcol = np.prod(vals[:age])
        return newcol
    
    df['newcol'] = df.apply(func, axis=1)
    

    En este código, la fila de entrada se pasa como un solo argumento a la función func. La primera línea extrae todas las columnas excepto la última (que se asume es la columna de edad) y las convierte en un arreglo numpy. La segunda línea extrae la columna de edad y la convierte en un entero. Luego, la función calcula la salida deseada y la devuelve.

    También puedes usar df.values para obtener un arreglo de numpy 2D con todos los valores de entrada:

    def func(row):
        vals = np.array(row[:-1], dtype='int')  # Extrae todas las columnas excepto la última
        age = int(row[-1])  # Extrae la columna de edad y convierte a entero
        newcol = np.prod(vals[:age])
        return newcol
    
    vfunc = np.vectorize(func)
    df['newcol'] = vfunc(df.values)
    

    Este código es similar al anterior, pero usa df.values para obtener un arreglo de numpy 2D con todos los valores de entrada en lugar de pasar una fila como un argumento separado a la función. La función vfunc luego aplica la función func elemento por elemento a este arreglo, calculando la salida para cada fila. Es importante destacar que np.vectorize no es tan eficiente como usar apply o un bucle, pero puede ser útil en algunos casos en los que necesitas aplicar una función personalizada a un arreglo de numpy.

Comments are closed.