Renvoyer une liste apply
est une opération dangereuse car l'objet résultant n'est pas garanti d'être une série ou un DataFrame. Et des exceptions pourraient être soulevées dans certains cas. Passons en revue un exemple 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
Il y a trois résultats possibles en renvoyant une liste de apply
1) Si la longueur de la liste renvoyée n'est pas égale au nombre de colonnes, une série de listes est renvoyée.
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) Lorsque la longueur de la liste retournée est égale au nombre de colonnes, un DataFrame est renvoyé et chaque colonne obtient la valeur correspondante dans la liste.
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 longueur de la liste retournée est égale au nombre de colonnes pour la première ligne mais a au moins une ligne où la liste a un nombre d'éléments différent du nombre de colonnes, une ValueError est levée.
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)
Répondre au problème sans appliquer
L'utilisation apply
avec axe = 1 est très lente. Il est possible d'obtenir de bien meilleures performances (en particulier sur des ensembles de données plus importants) avec des méthodes itératives de base.
Créer une trame de données plus grande
df1 = df.sample(100000, replace=True).reset_index(drop=True)
Timings
# 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 répond
%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)