web-dev-qa-db-fra.com

Pandas Python: fonction "Réduire" pour les séries

Existe-t-il un analogue pour reduce pour une série de pandas?

Par exemple, l'analogue pour map est pd.Series.apply , mais je ne trouve aucun analogue pour reduce


Ma demande est, j'ai une série de listes de pandas:

>>> business["categories"].head()

0                      ['Doctors', 'Health & Medical']
1                                        ['Nightlife']
2                 ['Active Life', 'Mini Golf', 'Golf']
3    ['Shopping', 'Home Services', 'Internet Servic...
4    ['Bars', 'American (New)', 'Nightlife', 'Loung...
Name: categories, dtype: object

J'aimerais fusionner la série de listes en utilisant reduce, comme suit:

categories = reduce(lambda l1, l2: l1 + l2, categories)

mais cela prend un temps horrible car la fusion de deux listes constitue le temps O(n) en Python. J'espère que pd.Series aura un moyen vectorisé d'accomplir cela plus rapidement.

15
hlin117

Avec itertools.chain() sur les valeurs

Cela pourrait être plus rapide:

from itertools import chain
categories = list(chain.from_iterable(categories.values))

Performance

from functools import reduce
from itertools import chain

categories = pd.Series([['a', 'b'], ['c', 'd', 'e']] * 1000)

%timeit list(chain.from_iterable(categories.values))
1000 loops, best of 3: 231 µs per loop

%timeit list(chain(*categories.values.flat))
1000 loops, best of 3: 237 µs per loop

%timeit reduce(lambda l1, l2: l1 + l2, categories)
100 loops, best of 3: 15.8 ms per loop

Pour cet ensemble de données, la variable chaining est environ 68 fois plus rapide.

La vectorisation?

La vectorisation fonctionne lorsque vous avez des types de données NumPy natifs (les pandas utilisent NumPy pour ses données après tout). Puisque nous avons déjà des listes dans la série et que nous voulons une liste comme résultat, il est plutôt improbable que la vectorisation accélère les choses. La conversion entre les objets Python standard et les types de données pandas/NumPy consommera probablement toutes les performances que vous pourriez obtenir de la vectorisation. J'ai fait une tentative de vectoriser l'algorithme dans une autre réponse.

15
Mike Müller

Vectorisé mais lent

Vous pouvez utiliser la variable concatenate de NumPy:

import numpy as np

list(np.concatenate(categories.values))

Performance

Mais nous avons déjà des listes, c’est-à-dire des objets Python. La vectorisation doit donc basculer entre les objets Python et les types de données NumPy. Cela ralentit les choses: 

categories = pd.Series([['a', 'b'], ['c', 'd', 'e']] * 1000)

%timeit list(np.concatenate(categories.values))
100 loops, best of 3: 7.66 ms per loop

%timeit np.concatenate(categories.values)
100 loops, best of 3: 5.33 ms per loop

%timeit list(chain.from_iterable(categories.values))
1000 loops, best of 3: 231 µs per loop
2
Mike Müller

Vous pouvez tenter votre chance avec business["categories"].str.join(''), mais je suppose que Pandas utilise les fonctions de chaîne Pythons. Je doute que vous puissiez faire mieux que ce que Python vous propose déjà.

0
ssm