La sortie de différence dans les deux Pandas dataframes à côté de mise en évidence de la différence
Je suis en train de mettre en évidence exactement ce qui a changé entre les deux dataframes.
Supposons que j'ai deux Python Pandas dataframes:
"StudentRoster Jan-1":
id Name score isEnrolled Comment
111 Jack 2.17 True He was late to class
112 Nick 1.11 False Graduated
113 Zoe 4.12 True
"StudentRoster Jan-2":
id Name score isEnrolled Comment
111 Jack 2.17 True He was late to class
112 Nick 1.21 False Graduated
113 Zoe 4.12 False On vacation
Mon objectif est de produire un tableau HTML:
- Identifie les lignes qui ont changé (peut être de type int, float, boolean, string)
-
Sorties lignes avec le même, ANCIENNES et les NOUVELLES valeurs (idéalement dans un tableau HTML) de sorte que le consommateur peut voir clairement ce qui a changé entre les deux dataframes:
"StudentRoster Difference Jan-1 - Jan-2": id Name score isEnrolled Comment 112 Nick was 1.11| now 1.21 False Graduated 113 Zoe 4.12 was True | now False was "" | now "On vacation"
Je suppose que je pourrais le faire ligne par ligne et colonne par colonne, de la comparaison, mais est-il un moyen plus facile?
Vous devez vous connecter pour publier un commentaire.
La première partie est similaire à Constantine, vous pouvez obtenir le booléen dont les lignes sont vides*:
Ensuite, nous pouvons voir les entrées qui ont changé:
Ici la première entrée est l'index et le deuxième les colonnes qui a été changé.
* Remarque: il est important que
df1
etdf2
partagent le même indice ici. Pour surmonter cette ambiguïté, vous pouvez vous assurer que vous regardez seulement l'partagé des étiquettes à l'aide dedf1.index & df2.index
, mais je pense que je vais laisser ça comme un exercice.df1
à ce qui est premier dansdf2
, indépendamment de la valeur de l'indice. JFYI dans le cas où je ne suis pas la seule personne pour qui ce n'était pas évident. ;D Merci!nan
dans les deux df1 et df1, cette fonction indique avoir changé denan
ànan
. C'est parce quenp.nan != np.nan
retourneTrue
.Mettant en relief la différence entre les deux DataFrames
Il est possible d'utiliser le DataFrame propriété de style pour mettre en surbrillance la couleur de fond des cellules où il y a une différence.
À l'aide de l'exemple de données à partir de la question d'origine
La première étape consiste à concaténer les DataFrames horizontalement avec le
concat
de la fonction et de la distinguer de chaque image avec lakeys
paramètre:Il est probablement plus facile pour échanger de la colonne et de mettre les mêmes noms de colonnes à côté les uns des autres:
Maintenant, son beaucoup plus facile de repérer les différences dans les images. Mais, on peut aller plus loin et d'utiliser le
style
propriété pour mettre en surbrillance les cellules qui sont différents. Nous définissons une fonction personnalisée pour ce faire vous pouvez le voir dans cette partie de la documentation.Cela permettra de mettre en surbrillance les cellules que les deux ont des valeurs manquantes. Vous pouvez les remplir ou de fournir de la logique supplémentaire, de sorte qu'ils n'ont pas mis en évidence.
df_final[(df != df2).any(1)].style.apply(highlight_diff, axis=None)
Cette réponse étend simplement @Andy Hayden, de faire de la résistance à quand les champs numériques sont
nan
, et de l'emballer dans une fonction.Donc avec vos données (légèrement modifié pour avoir un NaN dans le score de la colonne):
De sortie:
imprime
id
comme l'index, puisdf.groupby(level='id')
génère une erreur, et je ne sais pas pourquoi...J'ai été confronté à ce problème, mais a trouvé une réponse avant de trouver ce poste :
Basé sur unutbu réponse, charger vos données...
...définir votre diff fonction...
Alors il suffit d'utiliser un Panneau de conclure :
Par ailleurs, si vous êtes dans IPython Notebook, vous pouvez utiliser une couleur diff fonction
pour donner des couleurs en fonction de savoir si les cellules sont différents, égal ou gauche/droite null :
my_panel = pd.Panel(dict(df1=df1,df2=df2))
l'intérieur de la fonctionreport_diff()
? Je veux dire, est-il possible de faire cela:print report_diff(df1,df2)
et obtenir le même résultat que votre rapport d'impression?pd.Panel(dict(df1=df1,df2=df2)).apply(report_diff, axis=0)
- c'est génial!!!Si vos deux dataframes ont le même id dans les, puis trouver ce qui a changé, c'est en fait assez facile. Juste faire
frame1 != frame2
vous donnera un booléen DataFrame où chaqueTrue
est les données qui ont changé. De cela, vous pourriez facilement obtenir l'index de chaque ligne modifiée en faisantchangedids = frame1.index[np.any(frame1 != frame2,axis=1)]
.Une approche différente à l'aide de concat et drop_duplicates:
De sortie:
L'extension de réponse de @cge, ce qui est plutôt cool pour plus de lisibilité du résultat:
Démonstration complète exemple:
Après de bidouiller avec @journois réponse, j'ai été capable de le faire fonctionner à l'aide de MultiIndex au lieu de Panel, en raison de Panneau de deprication.
Tout d'abord, la création de certaines des données factices:
Ensuite, définir votre diff fonction, dans ce cas, je vais utiliser celui de sa réponse
report_diff
reste le même:Ensuite, je vais à concaténer les données dans un MultiIndex dataframe:
Et enfin, je vais appliquer la
report_diff
en bas de chaque groupe de colonnes:Ce sorties:
Et c'est tout!
Voici une autre manière à l'aide de sélectionner et de fusion:
Ici est la même chose à partir d'une Jupyter capture d'écran:
Une fonction qui trouve asymétrique de la différence entre deux trames de données est mis en œuvre ci-dessous:
(Basé sur différence pour les pandas)
RÉSUMÉ: https://gist.github.com/oneryalcin/68cf25f536a25e65f0b3c84f9c118e03
Exemple: