Supposons que j'ai un DataFrame pandas (chargé à partir d'un fichier csv) avec cette structure (le nombre de colonnes var et err n'est pas fixe, il varie d'un fichier à l'autre) :
var_0; var_1; var_2;
32; 9; 41;
47; 22; 41;
15; 12; 32;
3; 4; 4;
10; 9; 41;
43; 21; 45;
32; 14; 32;
51; 20; 40;
Supposons que nous supprimons les colonnes err_ds_j et err_mean pour les besoins de cette question. Je dois effectuer une comparaison automatique des valeurs de chaque ligne avec les valeurs des autres lignes ; par exemple : je dois comparer la première ligne avec la deuxième, puis avec la troisième, puis avec la quatrième, et ainsi de suite, puis je dois prendre la deuxième ligne et la comparer avec la première, puis avec la troisième, et ainsi de suite pour le reste du DataFrame.
En allant plus loin dans le problème, je veux voir si pour chaque couple de lignes, toutes les valeurs "var_i" de l'une d'entre elles sont supérieures ou égales aux valeurs correspondantes de l'autre ligne. Si c'est le cas, la ligne avec les valeurs plus élevées est appelée DOMINANTE, et j'ajoute une ligne dans un autre DataFrame, avec cette structure :
SET_A; SET_B; DOMINANT_SET
0; 1; B
...
Où les valeurs SET_A et SET_B sont des indices du DataFrame csv, et DOMINANT_SET me dit laquelle des deux est le jeu dominant (ou s'il n'y en a pas, elle est simplement assignée comme "none"). J'ai trouvé la troisième colonne utile car elle m'aide à éviter la comparaison des lignes que j'ai déjà comparées dans l'autre sens (par exemple : comparer la ligne 1 avec la ligne 0 est inutile, car j'ai déjà comparé les lignes 0 et 1 précédemment).
Ainsi, pour ce fichier csv, la sortie produite devrait être (et l'est effectivement, avec mon code) :
SET_A SET_B DOMINANT_SET
1 0 1 B
2 0 2 none
3 0 3 A
4 0 4 A
5 0 5 B
6 0 6 none
7 0 7 none
8 1 2 A
9 1 3 A
10 1 4 A
11 1 5 none
12 1 6 A
13 1 7 none
14 2 3 A
15 2 4 none
16 2 5 B
17 2 6 B
18 2 7 B
19 3 4 B
20 3 5 B
21 3 6 B
22 3 7 B
23 4 5 B
24 4 6 none
25 4 7 none
26 5 6 A
27 5 7 none
28 6 7 B
J'ai déjà écrit tout le code pour ce problème particulier, et cela fonctionne très bien avec certains jeux de données de test (100 lignes échantillonnées à partir d'un jeu de données réel).
Voici un extrait du code pertinent :
import numpy as np
import pandas as pd
def couple_deja_teste(index1, index2, dataframe):
return (((dataframe['SET_A'] == index1) & (dataframe['SET_B'] == index2)).any()) | (((dataframe['SET_A'] == index2) & (dataframe['SET_B'] == index1)).any())
def verifier_dominance(ensemble_a, ensemble_b, index_i, index_j, dataframe):
longueur = dataframe.shape[0]
if np.all(ensemble_a >= ensemble_b):
print("CONFIGURATION DOMINANTE A > B TROUVÉE")
dataframe.loc[longueur+1] = [index_i,index_j,'A']
elif np.all(ensemble_b >= ensemble_a):
print("CONFIGURATION DOMINANTE B > A TROUVÉE")
dataframe.loc[longueur+1] = [index_i,index_j,'B']
else:
dataframe.loc[longueur+1] = [index_i,index_j,'none']
df = pd.read_csv('test.csv', sep=';')
dom_table_df = pd.DataFrame(columns=['SET_A','SET_B','DOMINANT_SET'])
df_longueur = df.shape[0]
var_num = df.shape[1]-1
a = None
b = None
for i in range(0, df_longueur):
a = df.iloc[i, 0:var_num].values
for j in range(0, df_longueur):
if j == i:
continue
b = df.iloc[j, 0:var_num].values
if couple_deja_teste(i,j,dom_table_df):
print("ATTENTION : configuration", i, j, "déjà comparée, sautant")
else:
print("Comparaison de la configuration à la ligne", i, "avec la configuration à la ligne", j)
verifier_dominance(a, b, i, j, dom_table_df)
print(dom_table_df)
Le problème est que, n'étant pas très compétent en python et en pandas (je les apprends depuis environ un mois et demi), ce code est bien sûr terriblement lent (pour des jeux de données avec, disons, de 1000 à 10000 lignes) car j'utilise des itérations dans mon algorithme. Je sais que je peux utiliser quelque chose appelé vectorisation, mais en lisant à ce sujet, je ne suis pas complètement sûr que ce soit bon pour mon cas d'utilisation.
Alors, comment pourrais-je accélérer les calculs ?