> Modules non standards > Pandas > Concaténations et jointures de dataframes
Concaténations et jointures de dataframes
Juxtaposition de dataframes :
- pour concaténer 2 dataframes (ou plus) ayant les mêmes colonnes les uns en dessous des autres :
df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}, index = [0, 1])
df2 = pandas.DataFrame({'A': [6, 7], 'B': [4, 9]}, index = [2, 3])
pandas.concat([df1, df2])
donne
A B
0 3 1
1 5 2
2 6 4
3 7 9
- on peut concaténer ainsi des dataframes même si les index sont identiques, ils seront juxtaposés avec des valeurs d'index répétées : df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}); df2 = pandas.DataFrame({'A': [6, 7], 'B': [4, 9]}); pandas.concat([df1, df2]) donne :
A B
0 3 1
1 5 2
0 6 4
1 7 9
- si les dataframes n'ont pas les mêmes colonnes, par défaut, des NaN sont mis aux endroits non définis : df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}); df2 = pandas.DataFrame({'A': [6, 7], 'C': [4, 9]}); pandas.concat([df1, df2]) donne :
A B C
0 3 1.0 NaN
1 5 2.0 NaN
0 6 NaN 4.0
1 7 NaN 9.0
- si les dataframes n'ont pas les mêmes colonnes et qu'on veut conserver seulement les colonnes communes, intersection (sans avoir de NaN) : pandas.concat([df1, df2], join = 'inner') donne :
A
0 3
1 5
0 6
1 7
(le défaut de join est 'outer', conservation de toutes les colonnes, leur réunion).
- on peut ignorer les valeurs de l'index dans la concaténation (met un index de 0 à n - 1) : df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}); df2 = pandas.DataFrame({'A': [6, 7], 'B': [4, 9]}); pandas.concat([df1, df2], ignore_index = True) donne :
A B
0 3 1
1 5 2
2 6 4
3 7 9
- on peut rajouter un niveau hierarchique d'index en attribuant une clef à chaque dataframe de départ : df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}); df2 = pandas.DataFrame({'A': [6, 7], 'B': [4, 9]}); pandas.concat([df1, df2], keys = ['a', 'b']) donne :
A B
a 0 3 1
1 5 2
b 0 6 4
1 7 9
(et du coup, reset_index() permet de passer les valeurs d'index 'a' et 'b' comme nouvelle colonne).
- plutôt que de donner un argument keys, on peut donner un dictionnaire de frames plutôt qu'une list, c'est équivalent : pandas.concat({'a': df1, 'b': df2}).
- juxtaposition de colonnes plutôt que de lignes : df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}); df2 = pandas.DataFrame({'C': [6, 7], 'D': [4, 9]}); pandas.concat([df1, df2], axis = 1) donne :
A B C D
0 3 1 6 4
1 5 2 7 9
(le défaut de concaténation des lignes est axis = 0)
- on peut concaténér des dataframes et des séries, par exemple df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}); s = pandas.Series([7, 9], name = 'C'); pandas.concat([df1, s], axis = 1) donne :
A B C
0 3 1 7
1 5 2 9
- éviter de faire des concaténations répétées, préférer construire une liste de dataframes et faire une seule concaténation, pour des raisons de performances.
Pour rajouter le total par colonne : pandas.concat([df, pandas.DataFrame(df.sum(), columns = ['total']).T])
Jointures : c'est le même principe qu'en sql :
- jointure simple (inner) qui par défaut utilise les noms des colonnes qui sont communs : df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}); df2 = pandas.DataFrame({'A': [5, 3, 7], 'C': [9, 2, 0]}); pandas.merge(df1, df2) donne :
A B C
0 3 1 2
1 5 2 9
- on peut aussi faire : df1.merge(df2)
- on peut indiquer explicitement les colonnes sur lequelles on veut faire la jointure si c'est une partie seulement des colonnes de même non : df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}); df2 = pandas.DataFrame({'A': [5, 3, 7], 'B': [9, 2, 0]}); pandas.merge(df1, df2, on = ['A']) (ou df1.merge(df2, on = ['A'])) donne :
A B_x B_y
0 3 1 2
1 5 2 9
- jointure externe : les lignes qui n'ont pas la clef commune sont quand mêmes présentes (comme en sql) : pandas.merge(df1, df2, how = 'outer')
A B C
0 3 1.0 2
1 5 2.0 9
2 7 NaN 0
- on peut aussi faire une jointure externe gauche ou droite comme en sql avec how = 'left' ou how = 'right'
- on peut changer les extensions rajoutées sur les colonnes de même nom non incluses dans la jointure (par défaut _x et -y) : pandas.merge(df1, df2, on = ['A'], suffixes = ('_1', '_2')) donne :
A B_1 B_2
0 3 1 2
1 5 2 9
- on peut aussi faire une jointure sur des colonnes qui ne s'appellent pas pareil dans les 2 dataframes : df1 = pandas.DataFrame({'C': [3, 5], 'B': [1, 2]}); df2 = pandas.DataFrame({'D': [5, 3, 7], 'E': [9, 2, 0]}); pandas.merge(df1, df2, left_on = ['C'], right_on = ['D']) donne :
B C D E
0 1 3 3 2
1 2 5 5 9
- on peut aussi faire une jointure sur l'index : df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}, index = [0, 1]); df2 = pandas.DataFrame({'D': [5, 3, 7], 'E': [9, 2, 0]}, index = [2, 1, 0]); df1.join(df2) donne :
A B D E
0 3 1 7 0
1 5 2 3 2
- et la jointure sur l'index peut aussi être externe (des 2 côtés ou d'un côté), par exemple : df1 = pandas.DataFrame({'A': [3, 5], 'B': [1, 2]}, index = [0, 1]); df2 = pandas.DataFrame({'D': [5, 3, 7], 'E': [9, 2, 0]}, index = [2, 1, 0]); df1.join(df2, how = 'outer') donne :
A B D E
0 3.0 1.0 7 0
1 5.0 2.0 3 2
2 NaN NaN 5 9
- la jointure sur les index peut aussi être faite avec pandas.merge(df1, df2, left_index = True, right_index = True) au lieu de df1.join(df2)
- pandas.merge(df1, df2, sort = False) : ne trie pas les colonnes de jointure dans l'ordre (le défaut est de les trier, mais cela a un impact sur la performance).
Jointure par index :
- df1.join(df2) : faite une jointure par l'index, par défaut, une left join.
- pandas.concat([df1, df2], axis = 1) : par défaut, fait une outer join.
- pandas.merge(df1, df2, left_index = True, right_index = True) : par défaut, fait une inner join
Copyright python-simple.com
programmer en python, tutoriel python, graphes en python, Aymeric Duclert