Devolver una lista de apply
es 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:
df = pd.DataFrame(data=np.random.randint(0, 5, (5,3)),
columns=['a', 'b', 'c'])
df
a b c
0 4 0 0
1 2 0 1
2 2 2 2
3 1 2 2
4 3 0 0
Hay tres resultados posibles al devolver una lista de apply
1) Si la longitud de la lista devuelta no es igual al número de columnas, se devuelve una serie de listas.
df.apply(lambda x: list(range(2)), axis=1) # returns a Series
0 [0, 1]
1 [0, 1]
2 [0, 1]
3 [0, 1]
4 [0, 1]
dtype: object
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.
df.apply(lambda x: list(range(3)), axis=1) # returns a DataFrame
a b c
0 0 1 2
1 0 1 2
2 0 1 2
3 0 1 2
4 0 1 2
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.
i = 0
def f(x):
global i
if i == 0:
i += 1
return list(range(3))
return list(range(4))
df.apply(f, axis=1)
ValueError: Shape of passed values is (5, 4), indices imply (5, 3)
Respondiendo el problema sin aplicar
Usar apply
con 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
df1 = df.sample(100000, replace=True).reset_index(drop=True)
Tiempos
# apply is slow with axis=1
%timeit df1.apply(lambda x: mylist[x['col_1']: x['col_2']+1], axis=1)
2.59 s ± 76.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# zip - similar to @Thomas
%timeit [mylist[v1:v2+1] for v1, v2 in zip(df1.col_1, df1.col_2)]
29.5 ms ± 534 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
@Thomas respuesta
%timeit list(map(get_sublist, df1['col_1'],df1['col_2']))
34 ms ± 459 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)