0
votes

Trouver toutes les combinaisons consistant à une ligne par multiples tableaux

  • J'ai plusieurs matrices de deux dimensions. li>
  • Je veux trouver toutes les combinaisons composées d'une rangée de chaque tableau. Li>

    Exemple: p>

    Disons que la matrice A a rangée A0, A1, A2. Disons que le tableau B a des rangées B0, B1 P>

    Les six combinaisons sont les suivantes: p>

    A0-B0, A0-B1, A1-B0, A1-B1, A2-B0, A2-B1 P>

    Dash représente la concaténation ( np.hstack code>) p>

    Comment faire cela rapidement pour arbitraire em> Nombre de tableaux (disons, a, b, c, ...)? p>

    Méthode rapide pour 2 tableaux: combinaison de toutes les lignes dans deux tableaux numpopy p>

    résultat du code pour la combinaison de 3 tableaux: P>

    import numpy as np
    
    def form_combinations(xs):
        tot_size = np.sum([x.shape[1] for x in xs])
        n_rows = [x.shape[0] for x in xs]
        out = np.empty(n_rows + [tot_size])
        n_cols = [x.shape[1] for x in xs]
        cs = np.cumsum([0] + n_cols)
        n = np.newaxis
        out[:, :, :, cs[0]:cs[1]] = xs[0][:, n, n, :]
        out[:, :, :, cs[1]:cs[2]] = xs[1][n, :, n, :]
        out[:, :, :, cs[2]:cs[3]] = xs[2][n, n, :, :]
        out = out.reshape(-1, tot_size)
        return out
    
    
    def main():
        xs = [
            np.arange(3)[np.newaxis, :],
            np.arange(5, 20).reshape(3, 5),
            np.arange(17, 38).reshape(3, 7)
        ]
        print(xs)
    
        out = form_combinations(xs)
        print(out)
    
    main()
    


5 commentaires

Regardez iTertools.combinations (vous pouvez ensuite chaîner vos résultats en utilisant < Code> ithertools.chain.from_iterable )


Pourquoi ? C'est certes plus rapide que votre méthode de toute façon. Ou si vous voulez quelque chose de Scipy / Numpy: sciped.misc.comb


Si vous regardez le code donné dans le DOC, c'est (comme indiqué ci-dessus) un gros équivalent pour la compréhension. Le code réel derrière elle est bien optimisé.


Le code exemple ne fait même pas une liste (ou une compréhension de liste de n_row * n_row * n_row .. itérations). C'est une mission de tableau numpy. C Vitesse de boucle Python.


Ainsi, utilisez C, si vous vous plaignez de Python. Python n'est pas du tout sur la vitesse. Si vous voulez une vitesse, vous devez utiliser une meilleure langue pour cela.


3 Réponses :


1
votes

Un moyen consiste à utiliser une compréhension de la liste où vous venez de boucler sur les trois tableaux d'annonce Utilisez htstack code> pour les empiler horizontalement.

%timeit np.array([np.hstack((i, j, k)) for i in a for j in b for k in c])

# 55.1 µs ± 2.61 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)


1 commentaires

Merci, mais avez besoin de le faire pour un nombre arbitraire de tableaux. iTertools.combination est la même que cette idée qui utilise des boucles de python lentes.



1
votes

Pour le nombre arbitraire de tableaux, une approche progressive: xxx


0 commentaires

1
votes

adapté de https://stackoverflow.com/a/49445693/7207392

>>> timeit(lambda: cartesian_product_pp([a,b,c]), number=1000)*1000
15.173833002336323
>>> timeit(lambda: combine([a,b,c]), number=1000)*1000
31.1394709860906
>>> timeit(lambda: np.array([np.hstack((i, j, k)) for i in a for j in b for k in c]), number=1000)*1000
51.15771805867553


0 commentaires