1
votes

Générer des plages à partir de tableaux de démarrages et d'arrêts

Étant donné 2 tableaux de départs et d'arrêts, y a-t-il un moyen de générer des tableaux de nombres séquentiels dans numpy sans recourir à des boucles? Par exemple:

np.linspace(start, stop, num=3, axis=1)
array([[1. , 2.5, 4. ],
       [3. , 4. , 5. ],
       [5. , 6. , 7. ]])

linspace est le plus proche de ce que je veux mais je dois utiliser le même nombre d'étapes pour chaque série:

start = np.array([1, 3, 5])
stop  = np.array([4, 5, 7])

# Expected result
[
 [1, 2, 3, 4],
 [3, 4, 5],
 [5, 6, 7]
]


1 commentaires

Étant donné que les résultats peuvent varier en longueur, vous devez effectuer une sorte d'itération de liste. L'approche linspace fonctionne car les sous-listes sont de taille cohérente. Il peut générer une liste et mettre à l'échelle les autres. Avec des longueurs variables, il n'y a pas de raccourci de tableau.


3 Réponses :


2
votes

Une compréhension de liste compte-t-elle comme étant "sans boucles"?

[list(range(a,b+1)) for (a,b) in zip(start, stop)]


3 commentaires

range (a, b) doit être range (a, b + 1) à la place.


Le "résultat attendu" dans la question ressemble à une liste de listes, je pense


Merci pour la réponse Simon. Le résultat peut être une liste ou un ndarray. Je recherche des opérations vectorisées puisque je les ai en boucle.




1
votes

La compréhension évidente des listes:

In [98]: np.linspace([1,3,5], [4,5,7], num=3, axis=1)                                                     
Out[98]: 
array([[1. , 2.5, 4. ],
       [3. , 4. , 5. ],
       [5. , 6. , 7. ]])
In [99]: timeit np.linspace([1,3,5], [4,5,7], num=3, axis=1)                                              
87.2 µs ± 260 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Notez que je commence par les listes, car elles sont plus rapides.

frompyfunc est un bon outil pour faire des tableaux d'objets dtype:

In [97]: timeit [list(range(i,j)) for i,j in zip([1,3,5],[5,6,8])]                                        
2.38 µs ± 44.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

mais c'est plus lent que la compréhension.

mais si nous générons des listes à la place, la compréhension est encore plus rapide: p >

In [94]: f = np.frompyfunc(np.arange, 2,1)                                                                
In [95]: f(np.array([1,3,5]), np.array([5,6,8]))                                                          
Out[95]: 
array([array([1, 2, 3, 4]), array([3, 4, 5]), array([5, 6, 7])],
      dtype=object)
In [96]: timeit f(np.array([1,3,5]), np.array([5,6,8]))                                                   
10.9 µs ± 36.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Mais regardez cet linspace magique et vectorisé :

In [92]: [np.arange(i,j) for i,j in zip([1,3,5],[5,6,8])]                                                 
Out[92]: [array([1, 2, 3, 4]), array([3, 4, 5]), array([5, 6, 7])]
In [93]: timeit [np.arange(i,j) for i,j in zip([1,3,5],[5,6,8])]                                          
4.46 µs ± 97.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

lent !!

Mais ceci est un petit exemple. Les classements peuvent changer avec des cas beaucoup plus volumineux. Dans tous les cas, ne supposez pas que «vectorisé» est toujours plus rapide. Il existe de nombreux cas où les opérations de liste Python sont plus rapides, en particulier lorsque les tailles sont modestes. Créer des tableaux numpy est un peu coûteux - même s'ils sont rapides une fois créés.


0 commentaires