Formation Python
Vous disposez d'un grand ensemble de données riche en informations intéressantes, mais vous ne savez pas par où commencer à l'explorer? Votre patron vous a-t-il demandé de générer des statistiques à partir de celui-ci, mais elles ne sont pas si faciles à extraire? Ce sont précisément les cas d'utilisation où Pandas et Python peut vous aider! Avec ces outils, vous serez en mesure de découper un grand ensemble de données en parties gérables et de tirer un aperçu de ces informations.
Dans ce didacticiel, vous apprendrez à:
- Calculer métriques sur vos données
- Effectuer requêtes de base et agrégations
- Découvrir et gérer les données incorrectes, les incohérences et les valeurs manquantes
- Visualiser vos données avec des tracés
Vous découvrirez également les différences entre les principales structures de données utilisées par Pandas et Python. Pour suivre, vous pouvez obtenir tous les exemples de code dans ce tutoriel sur le lien ci-dessous:
Configuration de votre environnement
Il y a quelques éléments dont vous aurez besoin pour commencer ce didacticiel. La première est une familiarité avec les structures de données intégrées de Python, en particulier les listes et les dictionnaires. Pour plus d'informations, consultez Listes et Tuples en Python et Dictionnaires en Python.
La deuxième chose dont vous aurez besoin est un environnement Python fonctionnel. Vous pouvez suivre dans n'importe quel terminal sur lequel Python 3 est installé. Si vous souhaitez voir une sortie plus agréable, en particulier pour le grand ensemble de données NBA avec lequel vous allez travailler, vous pouvez exécuter les exemples dans un bloc-notes Jupyter.
La dernière chose dont vous aurez besoin est la bibliothèque Pandas Python, que vous pouvez installer avec pip:
$ python -m pip installe des pandas
Vous pouvez également utiliser le gestionnaire de packages Conda:
Si vous utilisez la distribution Anaconda, alors vous êtes prêt à partir! Anaconda est déjà livré avec la bibliothèque Pandas Python installée.
Remarque: Avez-vous entendu parler de multiples gestionnaires de packages dans le monde Python et sont quelque peu confus sur lequel choisir? pépin
et conda
sont tous deux d'excellents choix, et ils ont chacun leurs avantages.
Si vous allez utiliser Python principalement pour le travail de science des données, alors conda
est peut-être le meilleur choix. dans le conda
écosystème, vous avez deux alternatives principales:
- Si vous souhaitez mettre rapidement en place un environnement de science des données stable et que cela ne vous dérange pas de télécharger 500 Mo de données, consultez la distribution Anaconda.
- Si vous préférez une configuration plus minimaliste, consultez la section sur l'installation de Miniconda dans Configuration de Python pour Machine Learning sur Windows.
Les exemples de ce didacticiel ont été testés avec Python 3.7 et Pandas 0.25.0, mais ils devraient également fonctionner dans les anciennes versions. Vous pouvez obtenir tous les exemples de code que vous verrez dans ce didacticiel dans un cahier Jupyter en cliquant sur le lien ci-dessous:
Commençons!
Utilisation de la bibliothèque Pandas Python
Maintenant que vous avez installé Pandas, il est temps de jeter un œil à un ensemble de données. Dans ce didacticiel, vous allez analyser les résultats NBA fournis par FiveThirtyEight dans un fichier CSV de 17 Mo. Créer un script download_nba_all_elo.py
pour télécharger les données:
importation demandes
download_url = "https://raw.githubusercontent.com/fivethirtyeight/data/master/nba-elo/nbaallelo.csv"
target_csv_path = "nba_all_elo.csv"
réponse = demandes.avoir(download_url)
réponse.raise_for_status() # Vérifiez que la demande a abouti
avec ouvert(target_csv_path, "wb") comme F:
F.écrire(réponse.contenu)
impression("Téléchargement prêt.")
Lorsque vous exécutez le script, il enregistre le fichier nba_all_elo.csv
dans votre répertoire de travail actuel.
Remarque: Vous pouvez également utiliser votre navigateur Web pour télécharger le fichier CSV.
Cependant, avoir un script de téléchargement présente plusieurs avantages:
- Vous pouvez savoir où vous avez obtenu vos données.
- Vous pouvez répéter le téléchargement à tout moment! C'est particulièrement pratique si les données sont souvent actualisées.
- Vous n'avez pas besoin de partager le fichier CSV de 17 Mo avec vos collègues. Habituellement, il suffit de partager le script de téléchargement.
Vous pouvez maintenant utiliser la bibliothèque Pandas Python pour jeter un œil à vos données:
>>> importation pandas comme pd
>>> nba = pd.read_csv("nba_all_elo.csv")
>>> type(nba)
Ici, vous suivez la convention d'importation de Pandas en Python avec le pd
alias. Ensuite, vous utilisez .read_csv ()
pour lire dans votre jeu de données et le stocker en tant que Trame de données
objet dans la variable nba
.
Remarque: Vos données ne sont-elles pas au format CSV? Pas de soucis! La bibliothèque Pandas Python fournit plusieurs fonctions similaires comme read_json ()
, read_html ()
, et read_sql_table ()
. Pour apprendre à travailler avec ces formats de fichiers, consultez la section Lecture et écriture de fichiers avec Pandas ou consultez la documentation.
Vous pouvez voir la quantité de données nba
contient:
>>> len(nba)
126314
>>> nba.forme
(126314, 23)
Vous utilisez la fonction intégrée Python len ()
pour déterminer le nombre de lignes. Vous utilisez également le .forme
attribut de Trame de données
pour voir son dimensionnalité. Le résultat est un tuple contenant le nombre de lignes et de colonnes.
Vous savez maintenant qu'il y a 126 314 lignes et 23 colonnes dans votre jeu de données. Mais comment pouvez-vous être sûr que l'ensemble de données contient vraiment des statistiques de basket-ball? Vous pouvez consulter les cinq premières lignes avec .tête()
:
Si vous suivez un cahier Jupyter, vous verrez un résultat comme celui-ci:
À moins que votre écran ne soit assez grand, votre sortie n'affichera probablement pas les 23 colonnes. Quelque part au milieu, vous verrez une colonne d'ellipses (...
) indiquant les données manquantes. Si vous travaillez dans un terminal, cela est probablement plus lisible que d'habiller de longues lignes. Cependant, les cahiers Jupyter vous permettront de faire défiler. Vous pouvez configurer Pandas pour afficher les 23 colonnes comme ceci:
>>> pd.set_option("display.max.columns", Aucun)
Bien qu'il soit pratique de voir toutes les colonnes, vous n'aurez probablement pas besoin de six décimales! Remplacez-le par deux:
>>> pd.set_option("display.precision", 2)
Pour vérifier que vous avez correctement modifié les options, vous pouvez exécuter .tête()
à nouveau, ou vous pouvez afficher les cinq dernières lignes avec .queue()
au lieu:
Maintenant, vous devriez voir toutes les colonnes et vos données doivent afficher deux décimales:
Vous pouvez découvrir d'autres possibilités de .tête()
et .queue()
avec un petit exercice. Pouvez-vous imprimer les trois dernières lignes de votre Trame de données
? Développez le bloc de code ci-dessous pour voir la solution:
Voici comment imprimer les trois dernières lignes de nba
:
Votre sortie devrait ressembler à ceci:
Vous pouvez voir les trois dernières lignes de votre jeu de données avec les options que vous avez définies ci-dessus.
Semblable à la bibliothèque standard Python, les fonctions dans Pandas sont également livrées avec plusieurs paramètres facultatifs. Chaque fois que vous tombez sur un exemple qui semble pertinent mais légèrement différent de votre cas d'utilisation, consultez la documentation officielle. Il y a de fortes chances que vous trouviez une solution en modifiant certains paramètres facultatifs!
Apprendre à connaître vos données
Vous avez importé un fichier CSV avec la bibliothèque Pandas Python et vous avez d'abord examiné le contenu de votre ensemble de données. Jusqu'à présent, vous n'avez vu que la taille de votre ensemble de données et ses première et dernière lignes. Ensuite, vous apprendrez à examinez vos données plus systématiquement.
Affichage des types de données
La première étape pour connaître vos données consiste à découvrir les différents types de données qu'elles contiennent. Bien que vous puissiez mettre quoi que ce soit dans une liste, les colonnes d'un Trame de données
contiennent des valeurs d'un type de données spécifique. Lorsque vous comparez les structures de données Pandas et Python, vous verrez que ce comportement accélère beaucoup plus les Pandas!
Vous pouvez afficher toutes les colonnes et leurs types de données avec .Info()
:
Cela produira la sortie suivante:
Vous verrez une liste de toutes les colonnes de votre ensemble de données et le type de données que contient chaque colonne. Ici, vous pouvez voir les types de données int64
, float64
, et objet
. Pandas utilise la bibliothèque NumPy pour travailler avec ces types. Plus tard, vous rencontrerez les plus complexes catégorique
type de données, que la bibliothèque Pandas Python implémente elle-même.
le objet
le type de données est spécial. Selon le Pandas Cookbook, les objet
le type de données est «un fourre-tout pour les colonnes que Pandas ne reconnaît pas comme tout autre type spécifique». En pratique, cela signifie souvent que toutes les valeurs de la colonne sont des chaînes.
Bien que vous puissiez stocker des objets Python arbitraires dans le objet
type de données, vous devez être conscient des inconvénients de le faire. Des valeurs étranges dans un objet
peut endommager les performances de Pandas et son interopérabilité avec d'autres bibliothèques. Pour plus d'informations, consultez le guide de démarrage officiel.
Affichage des statistiques de base
Maintenant que vous avez vu quels types de données se trouvent dans votre ensemble de données, il est temps d'obtenir une vue d'ensemble des valeurs que contient chaque colonne. Vous pouvez le faire avec .décris()
:
Cette fonction vous montre quelques statistiques descriptives de base pour toutes les colonnes numériques:
.décris()
analyse uniquement les colonnes numériques par défaut, mais vous pouvez fournir d'autres types de données si vous utilisez le comprendre
paramètre:
>>> importation engourdi comme np
>>> nba.décris(comprendre=np.objet)
.décris()
n'essayera pas de calculer une moyenne ou un écart type pour le objet
colonnes, car ils comprennent principalement des chaînes de texte. Cependant, il affichera toujours quelques statistiques descriptives:
Jetez un oeil à la team_id
et fran_id
Colonnes. Votre jeu de données contient 104 ID d'équipe différents, mais seulement 53 ID de franchise différents. De plus, l'ID d'équipe le plus fréquent est BOS
, mais l'ID de franchise le plus fréquent Lakers
. Comment est-ce possible? Vous devrez explorer un peu plus votre ensemble de données pour répondre à cette question.
Explorer votre jeu de données
L'analyse exploratoire des données peut vous aider à répondre aux questions sur votre ensemble de données. Par exemple, vous pouvez examiner la fréquence à laquelle des valeurs spécifiques se produisent dans une colonne:
>>> nba[[[["team_id"].value_counts()
BOS 5997
NYK 5769
LAL 5078
...
SDS 11
>>> nba[[[["fran_id"].value_counts()
Nom: team_id, Longueur: 104, dtype: int64
Lakers 6024
Celtics 5997
Knicks 5769
...
Huskies 60
Nom: fran_id, dtype: int64
Il semble qu'une équipe nommée "Lakers"
joué 6024 matchs, mais seulement 5078 d'entre eux ont été joués par les Los Angeles Lakers. Découvrez qui est l'autre "Lakers"
l'équipe est:
>>> nba.loc[[[[nba[[[["fran_id"] == "Lakers", "team_id"].value_counts()
LAL 5078
MNL 946
Nom: team_id, dtype: int64
En effet, les Lakers de Minneapolis ("MNL"
) a joué 946 matchs. Vous pouvez même savoir quand ils ont joué à ces jeux:
>>> nba.loc[[[[nba[[[["team_id"] == "MNL", "date_game"].min()
«1/1/1949»
>>> nba.loc[[[[nba[[[["team_id"] == "MNL", "date_game"].max()
«09/04/1959»
>>> nba.loc[[[[nba[[[["team_id"] == "MNL", "date_game"].agg(("min", "max"))
min 1/1/1949
max 4/9/1959
Nom: date_game, dtype: object
On dirait que les Lakers de Minneapolis ont joué entre les années 1949 et 1959. Cela explique pourquoi vous pourriez ne pas reconnaître cette équipe!
Vous avez également découvert pourquoi l'équipe des Celtics de Boston "BOS"
joué le plus de jeux dans l'ensemble de données. Analysons également un peu leur histoire. Découvrez combien de points les Boston Celtics ont marqués lors de tous les matchs contenus dans cet ensemble de données. Développez le bloc de code ci-dessous pour la solution:
Semblable à la .min ()
et .max ()
fonctions d'agrégation, vous pouvez également utiliser .somme()
:
>>> nba.loc[[[[nba[[[["team_id"] == "BOS", "pts"].somme()
626484
Les Boston Celtics ont marqué un total de 626 484 points.
Vous avez un avant-goût des capacités d'un Pandas Trame de données
. Dans les sections suivantes, vous développerez les techniques que vous venez d'utiliser, mais d'abord, vous zoomerez et apprendrez comment cette puissante structure de données fonctionne.
Apprendre à connaître les structures de données de Pandas
Alors qu’un Trame de données
fournit des fonctions qui peuvent sembler assez intuitives, les concepts sous-jacents sont un peu plus difficiles à comprendre. Pour cette raison, vous allez mettre de côté le vaste NBA Trame de données
et construire à partir de zéro des objets Pandas plus petits.
Comprendre les objets de série
La structure de données la plus élémentaire de Python est la liste, qui est également un bon point de départ pour se familiariser pandas.Series
objets. Créer un nouveau Séries
objet basé sur une liste:
>>> revenus = pd.Séries([[[[5555, 7000, 1980])
>>> revenus
0 5555
1 7000
2 1980
dtype: int64
Vous avez utilisé la liste [5555, 7000, 1980]
créer un Séries
objet appelé revenus
. UNE Séries
objet encapsule deux composants:
- Une séquence de valeurs
- Une séquence de identifiants, qui est l'indice
Vous pouvez accéder à ces composants avec .valeurs
et .indice
, respectivement:
>>> revenus.valeurs
tableau ([5555, 7000, 1980])
>>> revenus.indice
RangeIndex (start = 0, stop = 3, step = 1)
revenus.valeurs
renvoie les valeurs dans le Séries
, tandis que revenue.index
renvoie l'indice de position.
Remarque: Si vous connaissez NumPy, il peut être intéressant pour vous de noter que les valeurs d'un Séries
sont en fait des tableaux à n dimensions:
>>> type(revenus.valeurs)
Si vous n'êtes pas familier avec NumPy, alors ne vous inquiétez pas! Vous pouvez explorer les tenants et aboutissants de votre ensemble de données avec la bibliothèque Pandas Python seule. Cependant, si vous êtes curieux de savoir ce que les Pandas font dans les coulisses, consultez Look Ma, No For-Loops: Array Programming With NumPy.
Alors que Pandas s'appuie sur NumPy, une différence significative réside dans leur indexage. Tout comme un tableau NumPy, un Pandas Séries
possède également un indice entier implicitement défini. Cet indice implicite indique la position de l'élément dans le Séries
.
Cependant, un Séries
peut également avoir un type d'index arbitraire. Vous pouvez considérer cet index explicite comme des étiquettes pour une ligne spécifique:
>>> city_revenues = pd.Séries(
... [[[[4200, 8000, 6500],
... indice=[[[["Amsterdam", "Toronto", "Tokyo"]
... )
>>> city_revenues
Amsterdam 4200
Toronto 8000
Tokyo 6500
dtype: int64
Ici, l'index est une liste de noms de villes représentés par des chaînes. Vous avez peut-être remarqué que les dictionnaires Python utilisent également des indices de chaîne, et c'est une analogie pratique à garder à l'esprit! Vous pouvez utiliser les blocs de code ci-dessus pour distinguer deux types de Séries
:
revenus
: CetteSéries
se comporte comme une liste Python car elle n'a qu'un index positionnel.city_revenues
: CetteSéries
agit comme un dictionnaire Python car il comporte à la fois un index positionnel et un index d'étiquette.
Voici comment construire un Séries
avec un index d'étiquette d'un dictionnaire Python:
>>> city_employee_count = pd.Séries("Amsterdam": 5, "Tokyo": 8)
>>> city_employee_count
Amsterdam 5
Tokyo 8
dtype: int64
Les clés du dictionnaire deviennent l'index et les valeurs du dictionnaire sont les Séries
valeurs.
Tout comme les dictionnaires, Séries
également soutenir .clés()
et le dans
mot-clé:
>>> city_employee_count.clés()
Indice(['Amsterdam', 'Tokyo'], dtype = 'objet')
>>> "Tokyo" dans city_employee_count
Vrai
>>> "New York" dans city_employee_count
Faux
Vous pouvez utiliser ces méthodes pour répondre rapidement aux questions sur votre jeu de données.
Comprendre les objets DataFrame
Alors qu’un Séries
est une structure de données assez puissante, elle a ses limites. Par exemple, vous ne pouvez stocker qu'un seul attribut par clé. Comme vous l’avez vu avec nba
de données, qui comprend 23 colonnes, la bibliothèque Pandas Python a plus à offrir avec son Trame de données
. Cette structure de données est une séquence de Séries
objets qui partagent le même index.
Si vous avez suivi le Séries
exemples, alors vous devriez déjà avoir deux Séries
objets avec des villes comme clés:
city_revenues
city_employee_count
Vous pouvez combiner ces objets en un Trame de données
en fournissant un dictionnaire dans le constructeur. Les clés du dictionnaire deviendront les noms des colonnes et les valeurs devraient contenir le Séries
objets:
>>> city_data = pd.Trame de données(
... "revenu": city_revenues,
... "employee_count": city_employee_count
... )
>>> city_data
chiffre_employé
Amsterdam 4200 5,0
Tokyo 6500 8.0
Toronto 8000 NaN
Notez comment les pandas ont remplacé les disparus employee_count
valeur pour Toronto avec NaN
.
Le nouveau Trame de données
l'indice est l'union des deux Séries
indices:
>>> city_data.indice
Indice(['Amsterdam', 'Tokyo', 'Toronto'], dtype = 'objet')
Comme un Séries
, une Trame de données
stocke également ses valeurs dans un tableau NumPy:
>>> city_data.valeurs
tableau ([[4.2e+03, 5.0e+00],
[6.5e+03, 8.0e+00],
[8.0e+03, nan]])
Vous pouvez également vous référer aux 2 dimensions d'un Trame de données
comme axes:
>>> city_data.axes
[Indice([Indice([Index([Index(['Amsterdam', 'Tokyo', 'Toronto'], dtype = 'object'),
Indice(['revenue', 'employee_count'], dtype = 'object')]
>>> city_data.axes[[[[0]
Indice(['Amsterdam', 'Tokyo', 'Toronto'], dtype = 'objet')
>>> city_data.axes[[[[1]
Indice(['revenue', 'employee_count'], dtype = 'objet')
L'axe marqué par 0 est le index des lignes, et l'axe marqué par 1 est le index des colonnes. Il est important de connaître cette terminologie car vous rencontrerez plusieurs Trame de données
méthodes qui acceptent un axe
paramètre.
UNE Trame de données
est également une structure de données de type dictionnaire, il prend donc également en charge .clés()
et le dans
mot-clé. Cependant, pour un Trame de données
ceux-ci ne se rapportent pas à l'index, mais aux colonnes:
>>> city_data.clés()
Indice(['revenue', 'employee_count'], dtype = 'objet')
>>> "Amsterdam" dans city_data
Faux
>>> "revenu" dans city_data
Vrai
Vous pouvez voir ces concepts en action avec le plus grand ensemble de données NBA. Contient-il une colonne appelée "points"
ou s'appelait-il "pts"
? Pour répondre à cette question, affichez l'index et les axes du nba
jeu de données, puis développez le bloc de code ci-dessous pour la solution:
Parce que vous n'avez pas spécifié de colonne d'index lorsque vous lisez le fichier CSV, Pandas a attribué un RangeIndex
à la Trame de données
:
>>> nba.indice
RangeIndex (start = 0, stop = 126314, step = 1)
nba
, comme tout Trame de données
objets, a deux axes:
>>> nba.axes
[RangeIndex(start=0stop=126314step=1)[RangeIndex(start=0stop=126314step=1)[RangeIndex(start=0stop=126314step=1)[RangeIndex(start=0stop=126314step=1)
Indice(['gameorder''game_id''lg_id''_iscopy''year_id''date_game'['gameorder''game_id''lg_id''_iscopy''year_id''date_game'['gameorder''game_id''lg_id''_iscopy''year_id''date_game'['gameorder''game_id''lg_id''_iscopy''year_id''date_game'
'seasongame', 'is_playoffs', 'team_id', 'fran_id', 'pts', 'elo_i',
'elo_n', 'win_equiv', 'opp_id', 'opp_fran', 'opp_pts', 'opp_elo_i',
'opp_elo_n', 'game_location', 'game_result', 'prévision', 'notes'],
dtype = 'object')]
Vous pouvez vérifier l'existence d'une colonne avec .clés()
:
>>> "points" dans nba.clés()
Faux
>>> "pts" dans nba.clés()
Vrai
La colonne s'appelle "pts"
, ne pas "points"
.
Lorsque vous utilisez ces méthodes pour répondre à des questions sur votre jeu de données, n'oubliez pas de savoir si vous travaillez avec un Séries
ou un Trame de données
afin que votre interprétation soit exacte.
Accès aux éléments de série
Dans la section ci-dessus, vous avez créé un Pandas Séries
basé sur une liste Python et a comparé les deux structures de données. Vous avez vu comment un Séries
l'objet est similaire aux listes et aux dictionnaires de plusieurs manières. Une autre similitude est que vous pouvez utiliser le opérateur d'indexation ([]
) pour Séries
ainsi que.
Vous apprendrez également à utiliser deux pandas spécifiques méthodes d'accès:
.loc
.iloc
Vous verrez que ces méthodes d'accès aux données peuvent être beaucoup plus lisibles que l'opérateur d'indexation.
Utilisation de l'opérateur d'indexation
Rappelons qu'un Séries
a deux indices:
- Un index positionnel ou implicite, qui est toujours un
RangeIndex
- Une étiquette ou un index explicite, qui peut contenir tout objet lavable
Ensuite, revisitez le city_revenues
objet:
>>> city_revenues
Amsterdam 4200
Toronto 8000
Tokyo 6500
dtype: int64
Vous pouvez facilement accéder aux valeurs dans un Séries
avec les indices label et positionnels:
>>> city_revenues[[[["Toronto"]
8000
>>> city_revenues[[[[1]
8000
Vous pouvez également utiliser des indices et des tranches négatifs, comme vous le feriez pour une liste:
>>> city_revenues[[[[-1]
6500
>>> city_revenues[[[[1:]
Toronto 8000
Tokyo 6500
dtype: int64
>>> city_revenues[[[["Toronto":]
Toronto 8000
Tokyo 6500
dtype: int64
Si vous souhaitez en savoir plus sur les possibilités de l'opérateur d'indexation, consultez Lists and Tuples in Python.
En utilisant .loc
et .iloc
L'opérateur d'indexation ([]
) est pratique, mais il y a une mise en garde. Et si les étiquettes sont également des nombres? Dites que vous devez travailler avec un Séries
objet comme ceci:
>>> couleurs = pd.Séries(
... [[[["rouge", "violet", "bleu", "vert", "Jaune"],
... indice=[[[[1, 2, 3, 5, 8]
... )
>>> couleurs
1 rouge
2 pourpres
3 bleu
5 verts
8 jaune
dtype: objet
Ce qui sera couleurs[1]
revenir? Pour un indice positionnel, couleurs[1]
est "violet"
. Cependant, si vous passez par l'index d'étiquette, couleurs[1]
fait référence à "rouge"
.
La bonne nouvelle est que vous n’avez pas à vous en rendre compte! Au lieu de cela, pour éviter toute confusion, la bibliothèque Pandas Python fournit deux méthodes d'accès aux données:
.loc
se réfère à la index des étiquettes..iloc
se réfère à la indice de position.
Ces méthodes d'accès aux données sont beaucoup plus lisibles:
>>> couleurs.loc[[[[1]
'rouge'
>>> couleurs.iloc[[[[1]
'violet'
colours.loc[1]
revenu "rouge"
, l'élément avec l'étiquette 1
. colours.iloc[1]
revenu "violet"
, l'élément avec l'index 1
.
La figure suivante montre quels éléments .loc
et .iloc
faire référence à:
Encore, .loc
pointe vers l'index d'étiquette sur le côté droit de l'image. Pendant ce temps, .iloc
pointe vers l'index de position sur le côté gauche de l'image.
Il est plus facile de garder à l’esprit la distinction entre .loc
et .iloc
que de comprendre ce que l'opérateur d'indexation retournera. Même si vous connaissez toutes les bizarreries de l'opérateur d'indexation, il peut être dangereux de supposer que tous ceux qui lisent votre code ont également internalisé ces règles!
Remarque: En plus d'être déroutant pour Séries
avec des étiquettes numériques, l'opérateur d'indexation Python a quelques inconvénients de performance. Il est tout à fait correct de l'utiliser dans des sessions interactives pour une analyse ad hoc, mais pour le code de production, le .loc
et .iloc
les méthodes d'accès aux données sont préférables. Pour plus de détails, consultez la section du Guide de l'utilisateur Pandas sur l'indexation et la sélection des données.
.loc
et .iloc
prennent également en charge les fonctionnalités que vous attendez des opérateurs d'indexation, comme le découpage. Cependant, ces méthodes d'accès aux données ont une différence importante. Tandis que .iloc
exclut l'élément de fermeture, .loc
l'inclut. Jetez un oeil à ce bloc de code:
>>> # Renvoie les éléments avec l'index implicite: 1, 2
>>> couleurs.iloc[[[[1:3]
2 pourpres
3 bleu
dtype: objet
Si vous comparez ce code avec l'image ci-dessus, vous pouvez voir que colours.iloc[1:3]
renvoie les éléments avec le indices de position de 1
et 2
. L'élément de clôture "vert"
avec un indice de position de 3
est exclu.
D'autre part, .loc
comprend l'élément de fermeture:
>>> # Renvoie les éléments avec l'index explicite entre 3 et 8
>>> couleurs.loc[[[[3:8]
3 bleu
5 verts
8 jaune
dtype: objet
Ce bloc de code dit de retourner tous les éléments avec un index des étiquettes entre 3
et 8
. Ici, le point de clôture "Jaune"
a un indice d'étiquette de 8
et est inclus dans la sortie.
Vous pouvez également transmettre un indice positionnel négatif à .iloc
:
>>> couleurs.iloc[[[[-2]
'vert'
Vous commencez à la fin de la Séries
et retourner le deuxième élément.
Remarque: Il y avait autrefois un .ix
indexeur, qui tentait de deviner s'il devait appliquer une indexation positionnelle ou d'étiquette selon le type de données de l'index. Parce qu'il a causé beaucoup de confusion, il est obsolète depuis la version 0.20.0 de Pandas.
Il est fortement recommandé que vous ne pas utiliser .ix
pour l'indexation. Au lieu de cela, utilisez toujours .loc
pour l'indexation des étiquettes et .iloc
pour l'indexation positionnelle. Pour plus de détails, consultez le Guide de l'utilisateur Pandas.
Vous pouvez utiliser les blocs de code ci-dessus pour distinguer deux Séries
comportements:
- Vous pouvez utiliser
.iloc
sur unSéries
similaire à l'utilisation[]
sur un liste. - Vous pouvez utiliser
.loc
sur unSéries
similaire à l'utilisation[]
sur un dictionnaire.
N'oubliez pas ces distinctions lorsque vous accédez à des éléments de votre Séries
objets.
Accès aux éléments DataFrame
Depuis un Trame de données
consiste en Séries
objets, vous pouvez utiliser les mêmes outils pour accéder à ses éléments. La différence cruciale est la dimension du Trame de données
. Vous utiliserez l'opérateur d'indexation pour les colonnes et les méthodes d'accès .loc
et .iloc
sur les rangées.
Utilisation de l'opérateur d'indexation
Si vous pensez à un Trame de données
comme un dictionnaire dont les valeurs sont Séries
, il est donc logique que vous puissiez accéder à ses colonnes avec l'opérateur d'indexation:
>>> city_data[[[["revenu"]
Amsterdam 4200
Tokyo 6500
Toronto 8000
Nom: revenue, dtype: int64
>>> type(city_data[[[["revenu"])
pandas.core.series.Series
Ici, vous utilisez l'opérateur d'indexation pour sélectionner la colonne intitulée "revenu"
.
Si le nom de la colonne est une chaîne, vous pouvez également utiliser l'accès de style attribut avec la notation par points:
>>> city_data.revenu
Amsterdam 4200
Tokyo 6500
Toronto 8000
Nom: revenue, dtype: int64
city_data["revenue"]
et city_data.revenue
retourner la même sortie.
Il y a une situation où l'accès Trame de données
les éléments avec notation par points peuvent ne pas fonctionner ou peuvent créer des surprises. C'est quand un nom de colonne coïncide avec un Trame de données
nom d'attribut ou de méthode:
>>> jouets = pd.Trame de données([[[[
... "Nom": "Balle", "forme": "sphère",
... "Nom": "Rubik's Cube", "forme": "cube"
... ])
>>> jouets[[[["forme"]
0 sphère
1 cube
Nom: forme, dtype: objet
>>> jouets.forme
(2, 2)
L'opération d'indexation jouets["shape"]
renvoie les données correctes, mais l'opération de style attribut toys.shape
renvoie toujours la forme du Trame de données
. Vous ne devez utiliser l'accès de style attribut que dans des sessions interactives ou pour des opérations de lecture. Vous ne devez pas l'utiliser pour du code de production ou pour manipuler des données (telles que la définition de nouvelles colonnes).
En utilisant .loc
et .iloc
Semblable à Séries
, une Trame de données
fournit également .loc
et .iloc
méthodes d'accès aux données. Rappelles toi, .loc
utilise l'étiquette et .iloc
l'indice de position:
>>> city_data.loc[[[["Amsterdam"]
chiffre d'affaires 4200,0
employee_count 5.0
Nom: Amsterdam, dtype: float64
>>> city_data.loc[[[["Tokyo": "Toronto"]
revenue employee_count
Tokyo 6500 8.0
Toronto 8000 NaN
>>> city_data.iloc[[[[1]
chiffre d'affaires 6500,0
employee_count 8.0
Nom: Tokyo, dtype: float64
Chaque ligne de code sélectionne une ligne différente de city_data
:
city_data.loc["Amsterdam"]
sélectionne la ligne avec l'index d'étiquette"Amsterdam"
.city_data.loc["Tokyo": "Toronto"]
sélectionne les lignes avec des indices d'étiquette"Tokyo"
à"Toronto"
. Rappelles toi,.loc
est inclusif.city_data.iloc[1]
sélectionne la ligne avec l'indice de position1
, lequel est"Tokyo"
.
D'accord, vous avez utilisé .loc
et .iloc
sur les petites structures de données. Maintenant, il est temps de pratiquer avec quelque chose de plus grand! Utilisez une méthode d'accès aux données pour afficher l'avant-dernière ligne du nba
base de données. Développez ensuite le bloc de code ci-dessous pour voir une solution:
L'avant-dernier rang est le rang avec le indice de position de -2
. Vous pouvez l'afficher avec .iloc
:
>>> nba.iloc[[[[-2]
gameorder 63157
game_id 201506170CLE
lg_id NBA
_écopie 0
year_id 2015
date_game 16/06/2015
seasongame 102
is_playoffs 1
team_id CLE
fran_id Cavaliers
pts 97
elo_i 1700.74
elo_n 1692.09
win_equiv 59.2902
opp_id GSW
opp_fran Warriors
opp_pts 105
opp_elo_i 1813.63
opp_elo_n 1822.29
emplacement_jeu H
game_result L
prévision 0,48145
note NaN
Nom: 126312, dtype: objet
Vous verrez la sortie comme Séries
objet.
Pour un Trame de données
, les méthodes d'accès aux données .loc
et .iloc
accepter également un deuxième paramètre. Alors que le premier paramètre sélectionne des lignes en fonction des indices, le deuxième paramètre sélectionne les colonnes. Vous pouvez utiliser ces paramètres ensemble pour sélectionner un sous-ensemble de lignes et de colonnes de votre Trame de données
:
>>> city_data.loc[[[["Amsterdam": "Tokyo", "revenu"]
Amsterdam 4200
Tokyo 6500
Nom: revenue, dtype: int64
Notez que vous séparez les paramètres par une virgule (,
). Le premier paramètre, "Amsterdam": "Tokyo"
dit de sélectionner toutes les lignes entre ces deux étiquettes. Le deuxième paramètre vient après la virgule et dit de sélectionner le "revenu"
colonne.
Il est temps de voir la même construction en action avec le plus grand nba
base de données. Sélectionnez tous les jeux entre les étiquettes 5555
et 5559
. Vous n'êtes intéressé que par les noms des équipes et les scores, alors sélectionnez également ces éléments. Développez le bloc de code ci-dessous pour voir une solution:
Tout d'abord, définissez les lignes que vous souhaitez voir, puis répertoriez les colonnes pertinentes:
>>> nba.loc[[[[5555:5559, [[[["fran_id", "opp_fran", "pts", "opp_pts"]]
Tu utilises .loc
pour l'index d'étiquette et une virgule (,
) pour séparer vos deux paramètres.
Vous devriez voir une petite partie de votre assez grand ensemble de données:
La sortie est beaucoup plus facile à lire!
Avec des méthodes d'accès aux données comme .loc
et .iloc
, vous pouvez sélectionner juste le bon sous-ensemble de votre Trame de données
pour vous aider à répondre aux questions sur votre jeu de données.
Interroger votre ensemble de données
Vous avez vu comment accéder à des sous-ensembles d'un énorme ensemble de données en fonction de ses indices. Maintenant, vous allez sélectionner des lignes en fonction des valeurs des colonnes de votre ensemble de données à requete vos données. Par exemple, vous pouvez créer un nouveau Trame de données
qui ne contient que des jeux joués après 2010:
>>> current_decade = nba[[[[nba[[[["year_id"] > 2010]
>>> current_decade.forme
(12658, 23)
Vous avez toujours les 23 colonnes, mais votre nouveau Trame de données
se compose uniquement de lignes où la valeur dans le "year_id"
la colonne est supérieure à 2010
.
Vous pouvez également sélectionner les lignes où un champ spécifique n'est pas nul:
>>> games_with_notes = nba[[[[nba[[[["Remarques"].pas nul()]
>>> games_with_notes.forme
(5424, 23)
Cela peut être utile si vous souhaitez éviter toute valeur manquante dans une colonne. Vous pouvez aussi utiliser .notna ()
pour atteindre le même objectif.
Vous pouvez même accéder aux valeurs de la objet
type de données as str
et effectuer des méthodes de chaîne sur eux:
>>> ers = nba[[[[nba[[[["fran_id"].str.se termine par("ers")]
>>> ers.forme
(27797, 23)
Tu utilises .str.endswith ()
pour filtrer votre jeu de données et trouver tous les jeux où le nom de l'équipe à domicile se termine par "ers"
.
Vous pouvez combiner plusieurs critères et interroger également votre ensemble de données. Pour ce faire, assurez-vous de mettre chacun entre parenthèses et d'utiliser les opérateurs logiques |
et &
pour les séparer.
Faites une recherche des matchs de Baltimore où les deux équipes ont marqué plus de 100 points. Pour voir chaque jeu une seule fois, vous devez exclure les doublons:
>>> nba[[[[
... (nba[[[["_iscopy"] == 0) &
... (nba[[[["pts"] > 100) &
... (nba[[[["opp_pts"] > 100) &
... (nba[[[["team_id"] == "BLB")
... ]
Ici, vous utilisez nba["_iscopy"] == 0
pour inclure uniquement les entrées qui ne sont pas des copies.
Votre sortie doit contenir cinq jeux mouvementés:
Essayez de créer une autre requête avec plusieurs critères. Au printemps 1992, les deux équipes de Los Angeles ont dû jouer un match à domicile sur un autre terrain. Recherchez votre jeu de données pour trouver ces deux jeux. Les deux équipes ont un ID commençant par "LA"
. Développez le bloc de code ci-dessous pour voir une solution:
Vous pouvez utiliser .str
pour trouver les ID d'équipe commençant par "LA"
, et vous pouvez supposer qu'un jeu aussi inhabituel aurait quelques notes:
>>> nba[[[[
... (nba[[[["_iscopy"] == 0) &
... (nba[[[["team_id"].str.commence avec("LA")) &
... (nba[[[["year_id"]==1992) &
... (nba[[[["Remarques"].pas nul())
... ]
Votre sortie devrait montrer deux jeux le jour 5/3/1992:
Belle trouvaille!
Lorsque vous savez comment interroger votre ensemble de données avec plusieurs critères, vous pourrez répondre à des questions plus spécifiques sur votre ensemble de données.
Regroupement et agrégation de vos données
Vous pouvez également vouloir découvrir d'autres fonctionnalités de votre ensemble de données, comme la somme, la moyenne ou la valeur moyenne d'un groupe d'éléments. Heureusement, la bibliothèque Pandas Python propose fonctions de regroupement et d'agrégation pour vous aider à accomplir cette tâche.
UNE Séries
a plus de vingt méthodes différentes pour calculer les statistiques descriptives. Voici quelques exemples:
>>> city_revenues.somme()
18700
>>> city_revenues.max()
8000
La première méthode renvoie le total de city_revenues
, tandis que la seconde renvoie la valeur maximale. Il existe d'autres méthodes que vous pouvez utiliser, comme .min ()
et .signifier()
.
Rappelez-vous, une colonne d'un Trame de données
est en fait un Séries
objet. Pour cette raison, vous pouvez utiliser ces mêmes fonctions sur les colonnes de nba
:
>>> points = nba[[[["pts"]
>>> type(points)
>>> points.somme()
12976235
UNE Trame de données
peut avoir plusieurs colonnes, ce qui introduit de nouvelles possibilités d'agrégation, comme regroupement:
>>> nba.par groupe("fran_id", Trier=Faux)[[[["pts"].somme()
fran_id
Huskies 3995
Knicks 582497
Cerfs 20398
Falcons 3797
Capitols 22387
...
Par défaut, Pandas trie les touches de groupe pendant l'appel à .par groupe()
. Si vous ne voulez pas trier, passez sort = False
. Ce paramètre peut entraîner des gains de performances.
Vous pouvez également regrouper par plusieurs colonnes:
>>> nba[[[[
... (nba[[[["fran_id"] == "Éperons") &
... (nba[[[["year_id"] > 2010)
... ].par groupe([[[["year_id", "game_result"])[[[["identifiant de jeu"].compter()
year_id game_result
2011 L 25
W 63
2012 L 20
W 60
2013 L 30
W 73
2014 L 27
W 78
2015 L 31
W 58
Nom: game_id, dtype: int64
Vous pouvez pratiquer ces bases avec un exercice. Jetez un œil à la saison 2014-15 des Golden State Warriors (year_id: 2015
). Combien de victoires et de défaites ont-ils marquées au cours de la saison régulière et des séries éliminatoires? Développez le bloc de code ci-dessous pour la solution:
Tout d'abord, vous pouvez regrouper par "is_playoffs"
champ, puis par le résultat:
>>> nba[[[[
... (nba[[[["fran_id"] == "Guerriers") &
... (nba[[[["year_id"] == 2015)
... ].par groupe([[[["is_playoffs", "game_result"])[[[["identifiant de jeu"].compter()
is_playoffs game_result
0 L 15
W 67
1 L 5
W 16
is_playoffs = 0
montre les résultats de la saison régulière, et is_playoffs = 1
montre les résultats des éliminatoires.
Dans les exemples ci-dessus, vous n'avez fait qu'effleurer la surface des fonctions d'agrégation disponibles dans la bibliothèque Pandas Python. Pour voir plus d'exemples sur la façon de les utiliser, consultez Pandas GroupBy: Votre guide de regroupement des données en Python.
Manipulation des colonnes
Vous aurez besoin de savoir comment manipuler your dataset’s columns in different phases of the data analysis process. You can add and drop columns as part of the initial data cleaning phase, or later based on the insights of your analysis.
Create a copy of your original DataFrame
to work with:
>>> df = nba.copie()
>>> df.forme
(126314, 23)
You can define new columns based on the existing ones:
>>> df[[[["difference"] = df.pts - df.opp_pts
>>> df.forme
(126314, 24)
Here, you used the "pts"
et "opp_pts"
columns to create a new one called "difference"
. This new column has the same functions as the old ones:
>>> df[[[["difference"].max()
68
Here, you used an aggregation function .max()
to find the largest value of your new column.
You can also rename the columns of your dataset. It seems that "game_result"
et "game_location"
are too verbose, so go ahead and rename them now:
>>> renamed_df = df.rename(
... columns="game_result": "result", "game_location": "location"
... )
>>> renamed_df.Info()
RangeIndex: 126314 entries, 0 to 126313
Data columns (total 24 columns):
gameorder 126314 non-null int64
...
location 126314 non-null object
result 126314 non-null object
forecast 126314 non-null float64
notes 5424 non-null object
difference 126314 non-null int64
dtypes: float64(6), int64(8), object(10)
memory usage: 23.1+ MB
Note that there’s a new object, renamed_df
. Like several other data manipulation methods, .rename()
returns a new DataFrame
by default. If you want to manipulate the original DataFrame
directly, then .rename()
also provides an inplace
parameter that you can set to Vrai
.
Your dataset might contain columns that you don’t need. For example, Elo ratings may be a fascinating concept to some, but you won’t analyze them in this tutorial. You can delete the four columns related to Elo:
>>> df.forme
(126314, 24)
>>> elo_columns = [[[["elo_i", "elo_n", "opp_elo_i", "opp_elo_n"]
>>> df.laissez tomber(elo_columns, inplace=Vrai, axis=1)
>>> df.forme
(126314, 20)
Remember, you added the new column "difference"
in a previous example, bringing the total number of columns to 24. When you remove the four Elo columns, the total number of columns drops to 20.
Specifying Data Types
When you create a new DataFrame
, either by calling a constructor or reading a CSV file, Pandas assigns a data type to each column based on its values. While it does a pretty good job, it’s not perfect. If you choose the right data type for your columns upfront, then you can significantly improve your code’s performance.
Take another look at the columns of the nba
dataset:
You’ll see the same output as before:
Ten of your columns have the data type object
. Most of these object
columns contain arbitrary text, but there are also some candidates for data type conversion. For example, take a look at the date_game
column:
>>> df[[[["date_game"] = pd.to_datetime(df[[[["date_game"])
Here, you use .to_datetime()
to specify all game dates as datetime
objects.
Other columns contain text that are a bit more structured. le game_location
column can have only three different values:
>>> df[[[["game_location"].nunique()
3
>>> df[[[["game_location"].value_counts()
A 63138
H 63138
N 38
Name: game_location, dtype: int64
Which data type would you use in a relational database for such a column? You would probably not use a varchar
type, but rather an enum
. Pandas provides the categorical
data type for the same purpose:
>>> df[[[["game_location"] = pd.Categorical(df[[[["game_location"])
>>> df[[[["game_location"].dtype
CategoricalDtype(categories=['A', 'H', 'N'], ordered=False)
categorical
Les données has a few advantages over unstructured text. When you specify the categorical
data type, you make validation easier and save a ton of memory, as Pandas will only use the unique values internally. The higher the ratio of total values to unique values, the more space savings you’ll get.
Run df.info()
again. You should see that changing the game_location
data type from object
à categorical
has decreased the memory usage.
Remarque: le categorical
data type also gives you access to additional methods through the .cat
accessor. To learn more, check out the official docs.
You’ll often encounter datasets with too many text columns. An essential skill for data scientists to have is the ability to spot which columns they can convert to a more performant data type.
Take a moment to practice this now. Find another column in the nba
dataset that has a generic data type and convert it to a more specific one. You can expand the code block below to see one potential solution:
game_result
can take only two different values:
>>> df[[[["game_result"].nunique()
2
>>> df[[[["game_result"].value_counts()
L 63157
W 63157
To improve performance, you can convert it into a categorical
column:
>>> df[[[["game_result"] = pd.Categorical(df[[[["game_result"])
Vous pouvez utiliser df.info()
to check the memory usage.
As you work with more massive datasets, memory savings becomes especially crucial. Be sure to keep performance in mind as you continue to explore your datasets.
Cleaning Data
You may be surprised to find this section so late in the tutorial! Usually, you’d take a critical look at your dataset to fix any issues before you move on to a more sophisticated analysis. However, in this tutorial, you’ll rely on the techniques that you’ve learned in the previous sections to clean your dataset.
Missing Values
Have you ever wondered why .info()
shows how many non-null values a column contains? The reason why is that this is vital information. Null values often indicate a problem in the data-gathering process. They can make several analysis techniques, like different types of machine learning, difficult or even impossible.
When you inspect the nba
dataset with nba.info()
, you’ll see that it’s quite neat. Only the column notes
contains null values for the majority of its rows:
This output shows that the notes
column has only 5424 non-null values. That means that over 120,000 rows of your dataset have null values in this column.
Sometimes, the easiest way to deal with records containing missing values is to ignore them. You can remove all the rows with missing values using .dropna()
:
>>> rows_without_missing_data = nba.dropna()
>>> rows_without_missing_data.forme
(5424, 23)
Of course, this kind of data cleanup doesn’t make sense for your nba
dataset, because it’s not a problem for a game to lack notes. But if your dataset contains a million valid records and a hundred where relevant data is missing, then dropping the incomplete records can be a reasonable solution.
You can also drop problematic columns if they’re not relevant for your analysis. Pour ce faire, utilisez .dropna()
again and provide the axis=1
parameter:
>>> data_without_missing_columns = nba.dropna(axis=1)
>>> data_without_missing_columns.forme
(126314, 22)
Now, the resulting DataFrame
contains all 126,314 games, but not the sometimes empty notes
column.
If there’s a meaningful default value for your use case, then you can also replace the missing values with that:
>>> data_with_default_notes = nba.copie()
>>> data_with_default_notes[[[["notes"].fillna(
... valeur="no notes at all",
... inplace=Vrai
... )
>>> data_with_default_notes[[[["notes"].describe()
count 126314
unique 232
top no notes at all
freq 120890
Name: notes, dtype: object
Here, you fill the empty notes
rows with the string "no notes at all"
.
Invalid Values
Invalid values can be even more dangerous than missing values. Often, you can perform your data analysis as expected, but the results you get are peculiar. This is especially important if your dataset is enormous or used manual entry. Invalid values are often more challenging to detect, but you can implement some sanity checks with queries and aggregations.
One thing you can do is validate the ranges of your data. For this, .describe()
is quite handy. Recall that it returns the following output:
le year_id
varies between 1947 and 2015. That sounds plausible.
Qu'en est-il de pts
? How can the minimum be 0
? Let’s have a look at those games:
>>> nba[[[[nba[[[["pts"] == 0]
This query returns a single row:
It seems the game was forfeited. Depending on your analysis, you may want to remove it from the dataset.
Inconsistent Values
Sometimes a value would be entirely realistic in and of itself, but it doesn’t fit with the values in the other columns. You can define some query criteria that are mutually exclusive and verify that these don’t occur together.
In the NBA dataset, the values of the fields pts
, opp_pts
et game_result
should be consistent with each other. You can check this using the .empty
attribute:
>>> nba[([([([(nba[[[["pts"] > nba[[[["opp_pts"]) & (nba[[[["game_result"] != 'W')].vide
Vrai
>>> nba[([([([(nba[[[["pts"] < nba[[[["opp_pts"]) & (nba[[[["game_result"] != 'L')].vide
Vrai
Fortunately, both of these queries return an empty DataFrame
.
Be prepared for surprises whenever you’re working with raw datasets, especially if they were gathered from different sources or through a complex pipeline. You might see rows where a team scored more points than their opponent, but still didn’t win—at least, according to your dataset! To avoid situations like this, make sure you add further data cleaning techniques to your Pandas and Python arsenal.
Combining Multiple Datasets
In the previous section, you’ve learned how to clean a messy dataset. Another aspect of real-world data is that it often comes in multiple pieces. In this section, you’ll learn how to grab those pieces and combiner them into one dataset that’s ready for analysis.
Earlier, you combined two Series
objects into a DataFrame
based on their indices. Now, you’ll take this one step further and use .concat()
to combine city_data
with another DataFrame
. Say you’ve managed to gather some data on two more cities:
>>> further_city_data = pd.DataFrame(
... "revenue": [[[[7000, 3400], "employee_count":[[[[2, 2],
... indice=[[[["New York", "Barcelona"]
... )
This second DataFrame
contains info on the cities "New York"
et "Barcelona"
.
You can add these cities to city_data
en utilisant .concat()
:
>>> all_city_data = pd.concat([[[[city_data, further_city_data], sort=Faux)
>>> all_city_data
Amsterdam 4200 5.0
Tokyo 6500 8.0
Toronto 8000 NaN
New York 7000 2.0
Barcelona 3400 2.0
Now, the new variable all_city_data
contains the values from both DataFrame
objects.
Remarque: As of Pandas version 0.25.0, the sort
parameter’s default value is Vrai
, but this will change to Faux
bientôt. It’s good practice to provide an explicit value for this parameter to ensure that your code works consistently in different Pandas and Python versions. For more info, consult the Pandas User Guide.
By default, concat()
combines along axis=0
. In other words, it appends rows. You can also use it to append columns by supplying the parameter axis=1
:
>>> city_countries = pd.DataFrame(
... "country": [[[["Holland", "Japan", "Holland", "Canada", "Spain"],
... "capital": [[[[1, 1, 0, 0, 0],
... indice=[[[["Amsterdam", "Tokyo", "Rotterdam", "Toronto", "Barcelona"]
... )
>>> cities = pd.concat([[[[all_city_data, city_countries], axis=1, sort=Faux)
>>> cities
revenue employee_count country capital
Amsterdam 4200.0 5.0 Holland 1.0
Tokyo 6500.0 8.0 Japan 1.0
Toronto 8000.0 NaN Canada 0.0
New York 7000.0 2.0 NaN NaN
Barcelona 3400.0 2.0 Spain 0.0
Rotterdam NaN NaN Holland 0.0
Note how Pandas added NaN
for the missing values. If you want to combine only the cities that appear in both DataFrame
objects, then you can set the join
parameter to inner
:
>>> pd.concat([[[[all_city_data, city_countries], axis=1, join="inner")
revenue employee_count country capital
Amsterdam 4200 5.0 Holland 1
Tokyo 6500 8.0 Japan 1
Toronto 8000 NaN Canada 0
Barcelona 3400 2.0 Spain 0
While it’s most straightforward to combine data based on the index, it’s not the only possibility. Vous pouvez utiliser .merge()
to implement a join operation similar to the one from SQL:
>>> des pays = pd.DataFrame(
... "population_millions": [[[[17, 127, 37],
... "continent": [[[["Europe", "Asia", "North America"]
... , indice= [[[["Holland", "Japan", "Canada"])
>>> pd.merge(cities, des pays, left_on="country", right_index=Vrai)
Here, you pass the parameter left_on="country"
à .merge()
to indicate what column you want to join on. The result is a bigger DataFrame
that contains not only city data, but also the population and continent of the respective countries:
Note that the result contains only the cities where the country is known and appears in the joined DataFrame
.
.merge()
performs an inner join by default. If you want to include all cities in the result, then you need to provide the Comment
parameter:
>>> pd.merge(
... cities,
... des pays,
... left_on="country",
... right_index=Vrai,
... Comment="left"
... )
Avec ça la gauche
join, you’ll see all the cities, including those without country data:
Welcome back, New York & Barcelona!
Visualizing Your Pandas DataFrame
Data visualization is one of the things that works much better in a Jupyter notebook than in a terminal, so go ahead and fire one up. If you need help getting started, then check out Jupyter Notebook: An Introduction. You can also access the Jupyter notebook that contains the examples from this tutorial by clicking the link below:
Include this line to show plots directly in the notebook:
>>> %matplotlib inline
Tous les deux Series
et DataFrame
objects have a .plot()
method, which is a wrapper around matplotlib.pyplot.plot()
. By default, it creates a line plot. Visualize how many points the Knicks scored throughout the seasons:
>>> nba[[[[nba[[[["fran_id"] == "Knicks"].groupby("year_id")[[[["pts"].sum().plot()
This shows a line plot with several peaks and two notable valleys around the years 2000 and 2010:
You can also create other types of plots, like a bar plot:
>>> nba[[[["fran_id"].value_counts().tête(dix).plot(kind="bar")
This will show the franchises with the most games played:
The Lakers are leading the Celtics by a minimal edge, and there are six further teams with a game count above 5000.
Now try a more complicated exercise. In 2013, the Miami Heat won the championship. Create a pie plot showing the count of their wins and losses during that season. Then, expand the code block to see a solution:
First, you define a criteria to include only the Heat’s games from 2013. Then, you create a plot in the same way as you’ve seen above:
>>> nba[[[[
... (nba[[[["fran_id"] == "Heat") &
... (nba[[[["year_id"] == 2013)
... ][[[["game_result"].value_counts().plot(kind="pie")
Here’s what a champion pie looks like:
The slice of wins is significantly larger than the slice of losses!
Sometimes, the numbers speak for themselves, but often a chart helps a lot with communicating your insights. To learn more about visualizing your data, check out Interactive Data Visualization in Python With Bokeh.
Conclusion
In this tutorial, you’ve learned how to start exploring a dataset with the Pandas Python library. You saw how you could access specific rows and columns to tame even the largest of datasets. Speaking of taming, you’ve also seen multiple techniques to prepare and clean your data, by specifying the data type of columns, dealing with missing values, and more. You’ve even created queries, aggregations, and plots based on those.
Now you can:
- Work with
Series
etDataFrame
objets - Subset your data with
.loc
,.iloc
, and the indexing operator - Answer questions with queries, grouping, and aggregation
- Handle missing, invalid, and inconsistent data
- Visualize your dataset in a Jupyter notebook
This journey using the NBA stats only scratches the surface of what you can do with the Pandas Python library. You can power up your project with Pandas tricks, learn techniques to speed up Pandas in Python, and even dive deep to see how Pandas works behind the scenes. There are many more features for you to discover, so get out there and tackle those datasets!
You can get all the code examples you saw in this tutorial by clicking the link below:
[ad_2]