Supongamos que tengo un dfque tiene columnas de 'ID', 'col_1', 'col_2'. Y defino una función:
f = lambda x, y : my_function_expression.
Ahora quiero aplicar la fa df's dos columnas 'col_1', 'col_2'para calcular elemento gota una nueva columna 'col_3', algo así como:
df['col_3'] = df[['col_1','col_2']].apply(f)
# Pandas gives : TypeError: ('<lambda>() takes exactly 2 arguments (1 given)'
Cómo hacer ?
** ** Agregue una muestra detallada como a continuación ***
import pandas as pd
df = pd.DataFrame({'ID':['1','2','3'], 'col_1': [0,2,3], 'col_2':[1,4,5]})
mylist = ['a','b','c','d','e','f']
def get_sublist(sta,end):
return mylist[sta:end+1]
#df['col_3'] = df[['col_1','col_2']].apply(get_sublist,axis=1)
# expect above to output df as below
ID col_1 col_2 col_3
0 1 0 1 ['a', 'b']
1 2 2 4 ['c', 'd', 'e']
2 3 3 5 ['d', 'e', 'f']

festá haciendoRespuestas:
Aquí hay un ejemplo de uso
applyen el marco de datos, con el que estoy llamandoaxis = 1.Tenga en cuenta que la diferencia es que, en lugar de tratar de pasar dos valores a la función
f, reescriba la función para aceptar un objeto Serie pandas y luego indexe la Serie para obtener los valores necesarios.Dependiendo de su caso de uso, a veces es útil crear un
groupobjeto pandas y luego usarloapplyen el grupo.fuente
sumse resuelve con éxito mediante cualquiera de los métodos sugeridos hasta ahora.dfobjeto que definiste, otro enfoque (con resultados equivalentes) esdf.apply(lambda x: x[0] + x[1], axis = 1).Hay una forma limpia y de una línea de hacer esto en Pandas:
Esto permite
fser una función definida por el usuario con múltiples valores de entrada y utiliza nombres de columna (seguros) en lugar de índices numéricos (inseguros) para acceder a las columnas.Ejemplo con datos (basado en la pregunta original):
Salida de
print(df):Si los nombres de sus columnas contienen espacios o comparten un nombre con un atributo de marco de datos existente, puede indexar entre corchetes:
fuente
axis=1y se llamanamesu columna, en realidad no devolverá los datos de su columna, sino elindex. Similar a obtener elnameen agroupby(). Resolví esto cambiando el nombre de mi columna..locen el ejemplo. Puede ser necesario si adapta esto a otra configuración del problema (por ejemplo, trabajar con sectores).Una solución simple es:
fuente
Una pregunta interesante! mi respuesta de la siguiente manera:
Salida:
Cambié el nombre de la columna a ID, J1, J2, J3 para asegurar ID <J1 <J2 <J3, por lo que la columna se muestra en la secuencia correcta.
Una versión más breve:
fuente
El método que está buscando es Series.combine. Sin embargo, parece que se debe tener cuidado con los tipos de datos. En su ejemplo, usted (como hice cuando probé la respuesta) ingenuamente llamaría
Sin embargo, esto arroja el error:
Mi mejor suposición es que parece esperar que el resultado sea del mismo tipo que la serie que llama al método (df.col_1 aquí). Sin embargo, lo siguiente funciona:
fuente
La forma en que ha escrito f necesita dos entradas. Si observa el mensaje de error, dice que no está proporcionando dos entradas a f, solo una. El mensaje de error es correcto.
La falta de coincidencia se debe a que df [['' col1 ',' col2 ']] devuelve un único marco de datos con dos columnas, no dos columnas separadas.
Debe cambiar su f para que tome una sola entrada, mantenga el marco de datos anterior como entrada, luego divídalo en x, y dentro del cuerpo de la función. Luego haga lo que necesite y devuelva un valor único.
Necesita esta firma de función porque la sintaxis es .apply (f) Por lo tanto, f necesita tomar la única cosa = marco de datos y no dos cosas, que es lo que su f actual espera.
Como no ha proporcionado el cuerpo de f, no puedo ayudarlo en más detalles, pero esto debería proporcionar la salida sin cambiar fundamentalmente su código o usar algunos otros métodos en lugar de aplicar
fuente
Voy a votar por np.vectorize. Le permite disparar más de x número de columnas y no tratar con el marco de datos en la función, por lo que es ideal para funciones que no controla o hacer algo como enviar 2 columnas y una constante en una función (es decir, col_1, col_2, 'foo').
fuente
Devolver una lista de
applyes una operación peligrosa ya que no se garantiza que el objeto resultante sea una Serie o un Marco de datos. Y se pueden plantear excepciones en ciertos casos. Veamos un ejemplo simple:Hay tres resultados posibles al devolver una lista de
apply1) Si la longitud de la lista devuelta no es igual al número de columnas, se devuelve una serie de listas.
2) Cuando la longitud de la lista devuelta es igual al número de columnas, se devuelve un DataFrame y cada columna obtiene el valor correspondiente en la lista.
3) Si la longitud de la lista devuelta es igual al número de columnas para la primera fila pero tiene al menos una fila donde la lista tiene un número diferente de elementos que el número de columnas, se genera un ValueError.
Respondiendo el problema sin aplicar
Usar
applycon axis = 1 es muy lento. Es posible obtener un rendimiento mucho mejor (especialmente en conjuntos de datos más grandes) con métodos iterativos básicos.Crear un marco de datos más grande
Tiempos
@Thomas respuesta
fuente
Estoy seguro de que esto no es tan rápido como las soluciones que usan operaciones Pandas o Numpy, pero si no desea reescribir su función, puede usar map. Usando los datos de ejemplo originales:
Podríamos pasar tantos argumentos como quisiéramos a la función de esta manera. La salida es lo que queríamos
fuente
applyconaxis=1Mi ejemplo a tus preguntas:
fuente
Si tiene un gran conjunto de datos, puede usar una forma fácil pero más rápida (tiempo de ejecución) de hacerlo usando más rápido:
fuente
Supongo que no desea cambiar la
get_sublistfunción, y solo quiere usar elapplymétodo DataFrame para hacer el trabajo. Para obtener el resultado que desea, he escrito dos funciones de ayuda:get_sublist_listyunlist. Como sugiere el nombre de la función, primero obtenga la lista de sublistas, luego extraiga esa sublista de esa lista. Finalmente, necesitamos llamar a laapplyfunción para aplicar esas dos funciones aldf[['col_1','col_2']]DataFrame posteriormente.Si no utiliza
[]para encerrar laget_sublistfunción, laget_sublist_listfunción devolverá una lista simple, se elevaráValueError: could not broadcast input array from shape (3) into shape (2), como había mencionado @Ted Petrou.fuente