1
votes

créer un tableau numpy dans la boucle for sans utilisation de la concaténation

Je crée une simulation avec plusieurs boucles for. Mon objectif est de créer un tableau numpy avec toutes les valeurs. J'ai d'abord utilisé numpy.concatenate, car cela fait le travail. J'ai lu, cependant, que np.concatenate est très lent, donc je cherche une méthode plus rapide pour créer le tableau avec les valeurs Mon code:

import numpy as np
values = np.array([])
for n in [100,1000]:
    for m in [2,10,100]:
        for roh in [0.0,0.5,0.9]:
            values = np.concatenate((values,[n,m,roh,1,2])) 

Les valeurs 1, 2 ne sont que des exemples de valeurs et ne sont pas importantes pour cette question. Existe-t-il donc un moyen plus rapide / plus intelligent de créer un tableau numpy avec toutes les permutations de la boucle triple for?


0 commentaires

3 Réponses :


2
votes

itertools serait très pratique pour cela. Par exemple,

(a modifié cette réponse, répondant également aux questions de suivi)

import numpy as np
import itertools
n_list, m_list, rho_list = [100,1000], [2,10,100], [0.0,0.5,0.9]

f1, f2 = lambda mat: 1, lambda mat: 2 # change accordingly

def f(n, m, rho, f1, f2):
    distance_matrix = np.zeros((2, 2))
    ## replace accordingly
    return f1(distance_matrix), f2(distance_matrix)

ff = lambda n, m, rho: f(n, m, rho, f1, f2) 
values = np.array([[n, m, rho, *ff(n, m, rho)] for n, m, rho in itertools.product(n_list, m_list, rho_list)])

Le * ff (...) consiste à décompresser le tuple en deux valeurs distinctes.


7 commentaires

les valeurs 1 et 2 que j'avais dans ma question seront calculées en fonction de n, m, roh. Disons que ces valeurs seront stockées dans les variables "valeur1" et "valeur2". Pourrai-je également mettre en œuvre ces valeurs dans votre réponse?


Bien sûr, étant donné vos deux fonctions f1 et f2 pour calculer ces valeurs, vous faites values ​​= np.array ([[n, m, rho, f1 (n , m, rho), f2 (n, m, rho)] pour n, m, rho dans itertools.product (n_list, m_list, rho_list)])


J'ai testé votre réponse et celle de Michael Sidorov et j'ai posté mes résultats de test comme réponse. J'ai toujours voté pour votre réponse comme étant celle qui résout mon problème


Disons que par itération n, m, roh je veux créer plusieurs tableaux de valeurs comme vous l'avez montré mais les fonctions, dans le tableau, f1 () et f2 () pour tous ces tableaux de valeurs devraient dépendre d'une distance_matrix (créée avec chaque n, m, roh itération). Est-ce possible ? Donc, pour clarifier j'ai 18 permutations n, m, roh, soit 18 distance_matrices différentes pour lesquelles il y aura plusieurs tableaux de valeurs avec les fonctions f1 (distance_matrix) et f2 (distance_matrix). J'espère que ma question est claire


Vous pouvez fusionner f1 et f2 en une seule fonction f , dans laquelle vous assemblez la matrice de distance puis renvoyez le tuple f1 ( distance_matrix), f2 (distance_matrix) .


Je crée donc une fonction qui effectue tous les calculs et ne renvoie que toutes les valeurs dont j'ai besoin qui seront ensuite implémentées dans le tableau de valeurs? Donc, si je l'ai bien compris, la fonction créera la matrice de distance et calculera à partir d'elle toutes les valeurs qui seront ensuite renvoyées?


je vais l'essayer, merci beaucoup pour toutes les réponses



1
votes

Vous pouvez faire de la manière suivante:

np.array([[n,m,roh,1,2] for n in [100,1000] for m in [2,10,100] for roh in [0.0,0.5,0.9]])

Cheers.


0 commentaires

1
votes

Merci à "Peter Meisrimel" et "Michael Sidorov" pour leurs réponses. J'ai moi-même essayé, en créant d'abord un tableau vide, puis en insérant les valeurs dans le tableau vide. J'ai également implémenté les deux réponses et testé les performances de tous (y compris la concaténation). Pour mieux voir les différences de performances, j'ai augmenté considérablement la taille de mon n, m, roh. Voici mon code:

time with empty array: 0.203110933303833
time with itertools: 0.14061522483825684
time with normal np array: 0.15624260902404785
time with concatenation: 49.35244131088257

En exécutant ce code, j'ai obtenu le résultat suivant:

import numpy as np
import itertools
import time

rows = np.arange(40)
columns = np.arange(40)
rohs = np.arange(40)
num1 = np.array([1])
num2 = np.array([2])

start1 = time.time()
asd1 = np.empty((64000,5),dtype=np.float32)
iterator = 0
for a in rows:
    for s in columns:
        for d in rohs:
            asd1[iterator] = a,s,d,1,2
            iterator += 1
end1 = time.time()
print("time with empty array: "+str(end1-start1))

start2 = time.time()
asd2 = np.array([a for a in itertools.product(rows,columns,rohs,num1,num2)])
end2 = time.time()
print("time with itertools: "+str(end2-start2))

start3 = time.time()
asd3 = np.array([[n,m,roh,1,2] for n in rows for m in columns for roh in rohs])
end3 = time.time()
print("time with normal np array: "+str(end3-start3))

start4 = time.time()
asd4 = np.array([])
for i in rows:
    for j in columns:
        for k in rohs:
            asd4 = np.concatenate((asd4,[i,j,k,1,2]))
end4 = time.time()
print("time with concatenation: "+str(end4-start4))

Donc, pour conclure, les deux réponses données étaient substantiellement plus rapide que la méthode de concaténation, alors que l'utilisation d'un tableau vide était relativement rapide, l'utilisation d'itertools s'est avérée être le moyen le plus rapide d'aborder ce problème, la différence augmentant avec de plus grandes quantités de permutations.


0 commentaires