Ajout de tables#

Lors du traitement de plusieurs images, potentiellement en utilisant plusieurs bibliothèques de traitement d’images, une tâche courante consiste à combiner des tables.

Nous commençons avec deux petites tables de mesures qui auraient pu être obtenues à partir de différentes fonctions ou différentes bibliothèques.

import pandas as pd
table1 = pd.DataFrame({
    "label":       [1,   2,   3],
    "circularity": [0.3, 0.5, 0.7],
    "elongation":  [2.3, 3.4, 1.2],
    })
table1
label circularity elongation
0 1 0.3 2.3
1 2 0.5 3.4
2 3 0.7 1.2
table2 = pd.DataFrame({
    "label":    [3,   2,   1,   4],
    "area":     [22,  32,  25,  18],
    "skewness": [0.5, 0.6, 0.3, 0.3],
    })
table2
label area skewness
0 3 22 0.5
1 2 32 0.6
2 1 25 0.3
3 4 18 0.3

Combinaison des colonnes de tables#

Selon la documentation de pandas, il existe plusieurs façons de combiner des tables. Nous utilisons d’abord un exemple erroné pour mettre en évidence les pièges lors de la combinaison de tables.

Dans l’exemple suivant, les mesures des étiquettes 1 et 3 sont mélangées. De plus, l’une de nos tables ne contenait pas de mesures pour l’étiquette 4.

wrongly_combined_tables = pd.concat([table1, table2], axis=1)
wrongly_combined_tables
label circularity elongation label area skewness
0 1.0 0.3 2.3 3 22 0.5
1 2.0 0.5 3.4 2 32 0.6
2 3.0 0.7 1.2 1 25 0.3
3 NaN NaN NaN 4 18 0.3

Une meilleure façon de combiner les tables est la commande merge. Elle permet de spécifier explicitement sur quelle colonne les tables doivent être combinées. Les scientifiques des données parlent de ‘l’index’ ou de ‘l’identifiant’ des lignes dans les tables.

correctly_combined_tables1 = pd.merge(table1, table2, how='inner', on='label')
correctly_combined_tables1
label circularity elongation area skewness
0 1 0.3 2.3 25 0.3
1 2 0.5 3.4 32 0.6
2 3 0.7 1.2 22 0.5

Vous remarquerez peut-être que dans l’exemple ci-dessus, l’étiquette 4 est manquante. Nous pouvons également l’obtenir dans notre table en effectuant une jointure externe.

correctly_combined_tables2 = pd.merge(table1, table2, how='outer', on='label')
correctly_combined_tables2
label circularity elongation area skewness
0 1 0.3 2.3 25 0.3
1 2 0.5 3.4 32 0.6
2 3 0.7 1.2 22 0.5
3 4 NaN NaN 18 0.3
correctly_combined_tables2 = pd.merge(table1, table2, how='right', on='label')
correctly_combined_tables2
label circularity elongation area skewness
0 3 0.7 1.2 22 0.5
1 2 0.5 3.4 32 0.6
2 1 0.3 2.3 25 0.3
3 4 NaN NaN 18 0.3

Supposons qu’il y ait un nom de mesure commun provenant de différentes tables. Par exemple, la table3 ci-dessous contient également “elongation”.

table3 = pd.DataFrame({
    "label":    [3,   2,   1,   4],
    "area":     [22,  32,  25,  18],
    "skewness": [0.5, 0.6, 0.3, 0.3],
    "elongation":  [2.3, 3.4, 1.2, 1.1]
    })
table3
label area skewness elongation
0 3 22 0.5 2.3
1 2 32 0.6 3.4
2 1 25 0.3 1.2
3 4 18 0.3 1.1

L’application de merge conserve toujours les deux mesures dans des colonnes différentes.

correctly_combined_tables3 = pd.merge(table1, table3, how='outer', on='label')
correctly_combined_tables3 
label circularity elongation_x area skewness elongation_y
0 1 0.3 2.3 25 0.3 1.2
1 2 0.5 3.4 32 0.6 3.4
2 3 0.7 1.2 22 0.5 2.3
3 4 NaN NaN 18 0.3 1.1

Nous pouvons changer ‘x’ et ‘y’ en passant d’autres suffixes.

correctly_combined_tables3 = pd.merge(table1, table3, how='outer', on='label', suffixes=('_method1', '_method2'))
correctly_combined_tables3
label circularity elongation_method1 area skewness elongation_method2
0 1 0.3 2.3 25 0.3 1.2
1 2 0.5 3.4 32 0.6 3.4
2 3 0.7 1.2 22 0.5 2.3
3 4 NaN NaN 18 0.3 1.1

Combinaison des mesures de plusieurs fichiers image#

Lorsqu’on applique un flux de travail à de nombreuses images, on obtiendrait des tables avec les mêmes noms de colonnes, mais avec un nombre variable de lignes. Pour calculer des statistiques pour des dossiers entiers ou pour effectuer de l’apprentissage automatique, nous devons généralement concaténer ces tables, mais il est important de garder une trace des fichiers sources.

Ouvrons deux tables générées en appliquant le même flux de travail à différents fichiers.

df1 = pd.read_csv('../../data/BBBC007_20P1_POS0007_D_1UL.csv')
df1.head()
area intensity_mean major_axis_length minor_axis_length aspect_ratio
0 256 93.250000 19.995017 17.021559 1.174688
1 90 82.488889 15.939969 7.516326 2.120713
2 577 90.637782 35.324458 21.759434 1.623409
3 270 95.640741 20.229431 17.669052 1.144908
4 153 84.908497 15.683703 12.420475 1.262730
df2 = pd.read_csv('../../data/BBBC007_20P1_POS0010_D_1UL.csv')
df2.head()
area intensity_mean major_axis_length minor_axis_length aspect_ratio
0 139 96.546763 17.504104 10.292770 1.700621
1 360 86.613889 35.746808 14.983124 2.385805
2 43 91.488372 12.967884 4.351573 2.980045
3 140 73.742857 18.940508 10.314404 1.836316
4 144 89.375000 13.639308 13.458532 1.013432

Dans ce cas particulier où nous savons que nous avons les mêmes colonnes, nous pourrions les concaténer en une seule grande table.

big_df = pd.concat([df1, df2], axis=0)
big_df
area intensity_mean major_axis_length minor_axis_length aspect_ratio
0 256 93.250000 19.995017 17.021559 1.174688
1 90 82.488889 15.939969 7.516326 2.120713
2 577 90.637782 35.324458 21.759434 1.623409
3 270 95.640741 20.229431 17.669052 1.144908
4 153 84.908497 15.683703 12.420475 1.262730
... ... ... ... ... ...
42 315 91.133333 20.927095 19.209283 1.089426
43 206 94.262136 23.381879 11.669668 2.003646
44 45 68.377778 9.406371 6.276445 1.498678
45 33 76.727273 10.724275 4.174568 2.568955
46 16 76.750000 7.745967 2.783882 2.782433

111 rows × 5 columns

Le problème est que nous perdons leur identité source. Une solution facile est d’ajouter une nouvelle colonne avec le nom du fichier avant de les concaténer. Cela facilitera leur séparation ultérieure et leur tracé.

Lorsque nous donnons une seule valeur à une nouvelle colonne, elle est attribuée à toutes les lignes.

df1['file_name'] = 'BBBC007_20P1_POS0007_D_1UL'

df2['file_name'] = 'BBBC007_20P1_POS0010_D_1UL'
big_df = pd.concat([df1, df2], axis=0)
big_df
area intensity_mean major_axis_length minor_axis_length aspect_ratio file_name
0 256 93.250000 19.995017 17.021559 1.174688 BBBC007_20P1_POS0007_D_1UL
1 90 82.488889 15.939969 7.516326 2.120713 BBBC007_20P1_POS0007_D_1UL
2 577 90.637782 35.324458 21.759434 1.623409 BBBC007_20P1_POS0007_D_1UL
3 270 95.640741 20.229431 17.669052 1.144908 BBBC007_20P1_POS0007_D_1UL
4 153 84.908497 15.683703 12.420475 1.262730 BBBC007_20P1_POS0007_D_1UL
... ... ... ... ... ... ...
42 315 91.133333 20.927095 19.209283 1.089426 BBBC007_20P1_POS0010_D_1UL
43 206 94.262136 23.381879 11.669668 2.003646 BBBC007_20P1_POS0010_D_1UL
44 45 68.377778 9.406371 6.276445 1.498678 BBBC007_20P1_POS0010_D_1UL
45 33 76.727273 10.724275 4.174568 2.568955 BBBC007_20P1_POS0010_D_1UL
46 16 76.750000 7.745967 2.783882 2.782433 BBBC007_20P1_POS0010_D_1UL

111 rows × 6 columns

Maintenant, nous pouvons distinguer en toute sécurité la source de chaque ligne.