Divers problèmes d'analyse de données

Intermediate

This tutorial is from open-source community. Access the source code

Introduction

Dans ce laboratoire, vous apprendrez à travailler avec différents conteneurs de données Python et à utiliser les compréhensions de listes, d'ensembles et de dictionnaires. Vous explorerez également le module collections, qui fournit des outils utiles pour la manipulation des données.

Python offre des outils puissants pour la manipulation et l'analyse de données. Dans ce laboratoire, vous allez pratiquer l'utilisation des structures de données intégrées à Python et des outils spécialisés pour analyser différents ensembles de données. En commençant par un simple ensemble de données de portefeuille, vous passerez à l'analyse des données des bus de l'Autorité de transport de Chicago pour extraire des informations pertinentes.

Ceci est un Guided Lab, qui fournit des instructions étape par étape pour vous aider à apprendre et à pratiquer. Suivez attentivement les instructions pour compléter chaque étape et acquérir une expérience pratique. Les données historiques montrent que c'est un laboratoire de niveau débutant avec un taux de réussite de 82%. Il a reçu un taux d'avis positifs de 96% de la part des apprenants.

Travailler avec les dictionnaires et les données CSV

Commençons par examiner un simple ensemble de données sur les titres d'actions. Dans cette étape, vous apprendrez à lire des données à partir d'un fichier CSV et à les stocker dans un format structuré en utilisant des dictionnaires.

Un fichier CSV (Comma-Separated Values, valeurs séparées par des virgules) est un moyen courant de stocker des données tabulaires, où chaque ligne représente une ligne et les valeurs sont séparées par des virgules. Les dictionnaires en Python sont une puissante structure de données qui vous permet de stocker des paires clé - valeur. En utilisant des dictionnaires, nous pouvons organiser les données du fichier CSV d'une manière plus significative.

Tout d'abord, créez un nouveau fichier Python dans le WebIDE en suivant ces étapes :

  1. Cliquez sur le bouton "New File" dans le WebIDE.
  2. Nommez le fichier readport.py.
  3. Copiez et collez le code suivant dans le fichier :
## readport.py

import csv

## A function that reads a file into a list of dictionaries
def read_portfolio(filename):
    portfolio = []
    with open(filename) as f:
        rows = csv.reader(f)
        headers = next(rows)   ## Skip the header row
        for row in rows:
            record = {
                'name': row[0],
                'shares': int(row[1]),
                'price': float(row[2])
            }
            portfolio.append(record)
    return portfolio

Ce code définit une fonction read_portfolio qui effectue plusieurs tâches importantes :

  1. Il ouvre un fichier CSV spécifié par le paramètre filename. La fonction open est utilisée pour accéder au fichier, et l'instruction with garantit que le fichier est correctement fermé après avoir terminé de le lire.
  2. Il saute la ligne d'en-tête. La ligne d'en-tête contient généralement les noms des colonnes dans le fichier CSV. Nous utilisons next(rows) pour déplacer l'itérateur à la ligne suivante, sautant ainsi l'en-tête.
  3. Pour chaque ligne de données, il crée un dictionnaire. Les clés du dictionnaire sont 'name', 'shares' et 'price'. Ces clés nous aideront à accéder aux données de manière plus intuitive.
  4. Il convertit le nombre d'actions en entiers et les prix en nombres à virgule flottante. Cela est important car les données lues à partir du fichier CSV sont initialement au format chaîne de caractères, et nous avons besoin de valeurs numériques pour les calculs.
  5. Il ajoute chaque dictionnaire à une liste appelée portfolio. Cette liste contiendra tous les enregistrements du fichier CSV.
  6. Enfin, il retourne la liste complète de dictionnaires.

Maintenant, créons un fichier pour les données de transport en commun. Créez un nouveau fichier appelé readrides.py avec le contenu suivant :

## readrides.py

import csv

def read_rides_as_dicts(filename):
    """
    Read the CTA bus data as a list of dictionaries
    """
    records = []
    with open(filename) as f:
        rows = csv.reader(f)
        headers = next(rows)   ## Skip header
        for row in rows:
            route = row[0]
            date = row[1]
            daytype = row[2]
            rides = int(row[3])
            record = {
                'route': route,
                'date': date,
                'daytype': daytype,
                'rides': rides
            }
            records.append(record)
    return records

La fonction read_rides_as_dicts fonctionne de manière similaire à la fonction read_portfolio. Elle lit un fichier CSV lié aux données des bus de l'Autorité de transport de Chicago (CTA), saute la ligne d'en-tête, crée un dictionnaire pour chaque ligne de données et stocke ces dictionnaires dans une liste.

Maintenant, testons la fonction read_portfolio en ouvrant un terminal dans le WebIDE :

  1. Cliquez sur le menu "Terminal" et sélectionnez "New Terminal".
  2. Lancez l'interpréteur Python en tapant python3.
  3. Exécutez les commandes suivantes :
>>> from readport import read_portfolio
>>> portfolio = read_portfolio('/home/labex/project/portfolio.csv')
>>> from pprint import pprint
>>> pprint(portfolio)
[{'name': 'AA', 'price': 32.2, 'shares': 100},
 {'name': 'IBM', 'price': 91.1, 'shares': 50},
 {'name': 'CAT', 'price': 83.44, 'shares': 150},
 {'name': 'MSFT', 'price': 51.23, 'shares': 200},
 {'name': 'GE', 'price': 40.37, 'shares': 95},
 {'name': 'MSFT', 'price': 65.1, 'shares': 50},
 {'name': 'IBM', 'price': 70.44, 'shares': 100}]

La fonction pprint (affichage formaté) est utilisée ici pour afficher les données dans un format plus lisible. Chaque élément de la liste est un dictionnaire représentant une action détenue. Le dictionnaire a les clés suivantes :

  • Un symbole d'action (name) : C'est l'abréviation utilisée pour identifier l'action.
  • Nombre d'actions détenues (shares) : Cela indique combien d'actions de l'action sont détenues.
  • Prix d'achat par action (price) : C'est le prix auquel chaque action a été achetée.

Notez que certaines actions comme 'MSFT' et 'IBM' apparaissent plusieurs fois. Cela représente différents achats de la même action, qui ont peut - être été effectués à différents moments et à différents prix.

Utilisation des compréhensions de listes, d'ensembles et de dictionnaires

Les compréhensions en Python sont un moyen très utile et concis de créer de nouvelles collections à partir d'existantes. Les collections en Python peuvent être des listes, des ensembles ou des dictionnaires, qui sont comme des conteneurs pour différents types de données. Les compréhensions vous permettent de filtrer certaines données, de les transformer d'une certaine manière et de les organiser plus efficacement. Dans cette partie, nous allons utiliser nos données de portefeuille pour explorer le fonctionnement de ces compréhensions.

Tout d'abord, vous devez ouvrir un terminal Python, comme vous l'avez fait à l'étape précédente. Une fois le terminal ouvert, vous allez entrer les exemples suivants un par un. Cette approche pratique vous aidera à comprendre le fonctionnement des compréhensions dans la pratique.

Compréhensions de listes

Une compréhension de liste est une syntaxe spéciale en Python qui crée une nouvelle liste. Elle le fait en appliquant une expression à chaque élément d'une collection existante.

Commençons par un exemple. Tout d'abord, nous allons importer une fonction pour lire nos données de portefeuille. Ensuite, nous utiliserons une compréhension de liste pour filtrer certains titres du portefeuille.

>>> from readport import read_portfolio
>>> portfolio = read_portfolio('/home/labex/project/portfolio.csv')

## Find all holdings with more than 100 shares
>>> large_holdings = [s for s in portfolio if s['shares'] > 100]
>>> print(large_holdings)
[{'name': 'CAT', 'shares': 150, 'price': 83.44}, {'name': 'MSFT', 'shares': 200, 'price': 51.23}]

Dans ce code, nous importons d'abord la fonction read_portfolio et l'utilisons pour lire les données du portefeuille à partir d'un fichier CSV. Ensuite, la compréhension de liste [s for s in portfolio if s['shares'] > 100] parcourt chaque élément s de la collection portfolio. Elle n'inclut l'élément s dans la nouvelle liste large_holdings que si le nombre d'actions de ce titre est supérieur à 100.

Les compréhensions de listes peuvent également être utilisées pour effectuer des calculs. Voici quelques exemples :

## Calculate the total cost of each holding (shares * price)
>>> holding_costs = [s['shares'] * s['price'] for s in portfolio]
>>> print(holding_costs)
[3220.0, 4555.0, 12516.0, 10246.0, 3835.15, 3255.0, 7044.0]

## Calculate the total cost of the entire portfolio
>>> total_portfolio_cost = sum([s['shares'] * s['price'] for s in portfolio])
>>> print(total_portfolio_cost)
44671.15

Dans le premier exemple, la compréhension de liste [s['shares'] * s['price'] for s in portfolio] calcule le coût total de chaque titre en multipliant le nombre d'actions par le prix pour chaque élément du portfolio. Dans le deuxième exemple, nous utilisons la fonction sum avec la compréhension de liste pour calculer le coût total de l'ensemble du portefeuille.

Compréhensions d'ensembles

Une compréhension d'ensemble est utilisée pour créer un ensemble à partir d'une collection existante. Un ensemble est une collection qui ne contient que des valeurs uniques.

Voyons comment cela fonctionne avec nos données de portefeuille :

## Find all unique stock names
>>> unique_stocks = {s['name'] for s in portfolio}
>>> print(unique_stocks)
{'MSFT', 'IBM', 'AA', 'GE', 'CAT'}

Dans ce code, la compréhension d'ensemble {s['name'] for s in portfolio} parcourt chaque élément s du portfolio et ajoute le nom de l'action (s['name']) à l'ensemble unique_stocks. Comme les ensembles ne stockent que des valeurs uniques, nous obtenons une liste de toutes les différentes actions de notre portefeuille sans doublons.

Compréhensions de dictionnaires

Une compréhension de dictionnaire crée un nouveau dictionnaire en appliquant des expressions pour créer des paires clé - valeur.

Voici un exemple d'utilisation d'une compréhension de dictionnaire pour compter le nombre total d'actions pour chaque action de notre portefeuille :

## Create a dictionary to count total shares for each stock
>>> totals = {s['name']: 0 for s in portfolio}
>>> for s in portfolio:
...     totals[s['name']] += s['shares']
...
>>> print(totals)
{'AA': 100, 'IBM': 150, 'CAT': 150, 'MSFT': 250, 'GE': 95}

Dans la première ligne, la compréhension de dictionnaire {s['name']: 0 for s in portfolio} crée un dictionnaire où chaque nom d'action (s['name']) est une clé, et la valeur initiale de chaque clé est 0. Ensuite, nous utilisons une boucle for pour parcourir chaque élément du portfolio. Pour chaque élément, nous ajoutons le nombre d'actions (s['shares']) à la valeur correspondante dans le dictionnaire totals.

Ces compréhensions sont très puissantes car elles vous permettent de transformer et d'analyser des données avec seulement quelques lignes de code. Elles sont un excellent outil à avoir dans votre boîte à outils de programmation Python.

Exploration du module collections

En Python, les conteneurs intégrés tels que les listes, les dictionnaires et les ensembles sont très utiles. Cependant, le module collections de Python va plus loin en fournissant des types de données de conteneurs spécialisés qui étendent les fonctionnalités de ces conteneurs intégrés. Examinons de plus près certains de ces types de données utiles.

Vous continuerez à travailler dans votre terminal Python et suivrez les exemples ci - dessous.

Counter

La classe Counter est une sous - classe du dictionnaire. Son objectif principal est de compter les objets hachables. Elle offre un moyen pratique de compter les éléments et prend en charge diverses opérations.

Tout d'abord, nous devons importer la classe Counter et une fonction pour lire un portefeuille. Ensuite, nous allons lire un portefeuille à partir d'un fichier CSV.

>>> from collections import Counter
>>> from readport import read_portfolio
>>> portfolio = read_portfolio('/home/labex/project/portfolio.csv')

Maintenant, nous allons créer un objet Counter pour compter le nombre d'actions pour chaque action en fonction de son nom.

## Create a counter to count shares by stock name
>>> totals = Counter()
>>> for s in portfolio:
...     totals[s['name']] += s['shares']
...
>>> print(totals)
Counter({'MSFT': 250, 'IBM': 150, 'CAT': 150, 'AA': 100, 'GE': 95})

L'une des grandes caractéristiques de l'objet Counter est qu'il initialise automatiquement les nouvelles clés avec un compte de 0. Cela signifie que vous n'avez pas besoin de vérifier si une clé existe avant d'incrémenter son compte, ce qui simplifie le code pour accumuler les comptes.

Les objets Counter ont également des méthodes spéciales. Par exemple, la méthode most_common() est très utile pour l'analyse de données.

## Get the two stocks with the most shares
>>> most_common_stocks = totals.most_common(2)
>>> print(most_common_stocks)
[('MSFT', 250), ('IBM', 150)]

De plus, les objets Counter peuvent être combinés à l'aide d'opérations arithmétiques.

## Create another counter
>>> more = Counter()
>>> more['IBM'] = 75
>>> more['AA'] = 200
>>> more['ACME'] = 30
>>> print(more)
Counter({'AA': 200, 'IBM': 75, 'ACME': 30})

## Add two counters together
>>> combined = totals + more
>>> print(combined)
Counter({'AA': 300, 'MSFT': 250, 'IBM': 225, 'CAT': 150, 'GE': 95, 'ACME': 30})

defaultdict

Le defaultdict est similaire à un dictionnaire classique, mais il a une caractéristique unique. Il fournit une valeur par défaut pour les clés qui n'existent pas encore. Cela peut simplifier votre code, car vous n'avez plus besoin de vérifier si une clé existe avant de l'utiliser.

>>> from collections import defaultdict

## Group portfolio entries by stock name
>>> byname = defaultdict(list)
>>> for s in portfolio:
...     byname[s['name']].append(s)
...
>>> print(byname['IBM'])
[{'name': 'IBM', 'shares': 50, 'price': 91.1}, {'name': 'IBM', 'shares': 100, 'price': 70.44}]
>>> print(byname['AA'])
[{'name': 'AA', 'shares': 100, 'price': 32.2}]

Lorsque vous créez un defaultdict(list), il crée automatiquement une nouvelle liste vide pour chaque nouvelle clé. Ainsi, vous pouvez directement ajouter un élément à la valeur d'une clé même si la clé n'existait pas auparavant. Cela élimine le besoin de vérifier si la clé existe et de créer manuellement une liste vide.

Vous pouvez également utiliser d'autres fonctions de fabrique par défaut. Par exemple, vous pouvez utiliser int, float ou même votre propre fonction personnalisée.

## Use defaultdict with int to count items
>>> word_counts = defaultdict(int)
>>> words = ['apple', 'orange', 'banana', 'apple', 'orange', 'apple']
>>> for word in words:
...     word_counts[word] += 1
...
>>> print(word_counts)
defaultdict(<class 'int'>, {'apple': 3, 'orange': 2, 'banana': 1})

Ces types de conteneurs spécialisés du module collections peuvent rendre votre code plus concis et efficace lorsque vous travaillez avec des données.

Défi d'analyse de données avec les données de l'Autorité de transport en commun de Chicago

Maintenant que vous avez pratiqué le travail avec différentes structures de données Python et le module collections, il est temps de mettre ces compétences en pratique dans une tâche d'analyse de données du monde réel. Dans cette expérience, nous allons analyser les données de fréquentation des bus de l'Autorité de transport en commun de Chicago (CTA). Cette application pratique vous aidera à comprendre comment utiliser Python pour extraire des informations significatives à partir de jeux de données du monde réel.

Compréhension des données

Tout d'abord, regardons les données de transport avec lesquelles nous allons travailler. Dans votre terminal Python, vous allez exécuter un peu de code pour charger les données et comprendre leur structure de base.

>>> import readrides
>>> rows = readrides.read_rides_as_dicts('/home/labex/project/ctabus.csv')
>>> print(len(rows))
## This will show the number of records in the dataset

>>> ## Let's look at the first record to understand the structure
>>> import pprint
>>> pprint.pprint(rows[0])

L'instruction import readrides importe un module personnalisé qui a une fonction pour lire les données à partir du fichier CSV. La fonction readrides.read_rides_as_dicts lit les données à partir du fichier CSV spécifié et convertit chaque ligne en un dictionnaire. len(rows) nous donne le nombre total d'enregistrements dans le jeu de données. En imprimant le premier enregistrement à l'aide de pprint.pprint(rows[0]), nous pouvons voir clairement la structure de chaque enregistrement.

Les données contiennent des enregistrements quotidiens de fréquentation pour différents itinéraires de bus. Chaque enregistrement comprend :

  • route : Le numéro de l'itinéraire de bus
  • date : La date au format "YYYY - MM - DD"
  • daytype : Soit "W" pour un jour de semaine, "A" pour un samedi, ou "U" pour un dimanche/jour férié
  • rides : Le nombre de passagers ce jour - là

Tâches d'analyse

Résolvons chacune des questions du défi une par une :

Question 1 : Combien d'itinéraires de bus existent à Chicago ?

Pour répondre à cette question, nous devons trouver tous les numéros d'itinéraire uniques dans le jeu de données. Nous utiliserons une compréhension d'ensemble pour cette tâche.

>>> ## Get all unique route numbers using a set comprehension
>>> unique_routes = {row['route'] for row in rows}
>>> print(len(unique_routes))

Une compréhension d'ensemble est un moyen concis de créer un ensemble. Dans ce cas, nous parcourons chaque ligne de la liste rows et extrayons la valeur route. Comme un ensemble ne stocke que des éléments uniques, nous obtenons un ensemble de tous les numéros d'itinéraire uniques. En imprimant la longueur de cet ensemble, nous obtenons le nombre total d'itinéraires de bus uniques.

Nous pouvons également voir quels sont certains de ces itinéraires :

>>> ## Print a few of the route numbers
>>> print(list(unique_routes)[:10])

Ici, nous convertissons l'ensemble d'itinéraires uniques en une liste et imprimons ensuite les 10 premiers éléments de cette liste.

Question 2 : Combien de personnes ont pris le bus numéro 22 le 2 février 2011 ?

Pour cette question, nous devons filtrer les données pour trouver l'enregistrement spécifique qui correspond à l'itinéraire et à la date donnés.

>>> ## Find rides on route 22 on February 2, 2011
>>> target_date = "2011-02-02"
>>> target_route = "22"
>>>
>>> for row in rows:
...     if row['route'] == target_route and row['date'] == target_date:
...         print(f"Rides on route {target_route} on {target_date}: {row['rides']}")
...         break

Nous définissons d'abord les variables target_date et target_route. Ensuite, nous parcourons chaque ligne de la liste rows. Pour chaque ligne, nous vérifions si l'itinéraire et la date correspondent à nos valeurs cibles. Si une correspondance est trouvée, nous imprimons le nombre de passagers et nous sortons de la boucle car nous avons trouvé l'enregistrement que nous recherchions.

Vous pouvez modifier ce code pour vérifier n'importe quel itinéraire à n'importe quelle date en changeant les variables target_date et target_route.

Question 3 : Quel est le nombre total de passagers par itinéraire de bus ?

Utilisons un Counter pour calculer le nombre total de passagers par itinéraire. Un Counter est une sous - classe de dictionnaire du module collections qui est utilisée pour compter les objets hachables.

>>> from collections import Counter
>>>
>>> ## Initialize a counter
>>> total_rides_by_route = Counter()
>>>
>>> ## Sum up rides for each route
>>> for row in rows:
...     total_rides_by_route[row['route']] += row['rides']
...
>>> ## View the top 5 routes by total ridership
>>> for route, rides in total_rides_by_route.most_common(5):
...     print(f"Route {route}: {rides:,} total rides")

Nous importons d'abord la classe Counter du module collections. Ensuite, nous initialisons un compteur vide appelé total_rides_by_route. Lorsque nous parcourons chaque ligne de la liste rows, nous ajoutons le nombre de passagers pour chaque itinéraire au compteur. Enfin, nous utilisons la méthode most_common(5) pour obtenir les 5 itinéraires avec le plus grand nombre total de passagers et imprimons les résultats.

Question 4 : Quels sont les cinq itinéraires de bus qui ont connu la plus forte augmentation de fréquentation sur dix ans de 2001 à 2011 ?

C'est une tâche plus complexe. Nous devons comparer la fréquentation en 2001 avec celle de 2011 pour chaque itinéraire.

>>> ## Create dictionaries to store total annual rides by route
>>> rides_2001 = Counter()
>>> rides_2011 = Counter()
>>>
>>> ## Collect data for each year
>>> for row in rows:
...     if row['date'].startswith('2001-'):
...         rides_2001[row['route']] += row['rides']
...     elif row['date'].startswith('2011-'):
...         rides_2011[row['route']] += row['rides']
...
>>> ## Calculate increases
>>> increases = {}
>>> for route in unique_routes:
...     if route in rides_2001 and route in rides_2011:
...         increase = rides_2011[route] - rides_2001[route]
...         increases[route] = increase
...
>>> ## Find the top 5 routes with the biggest increases
>>> import heapq
>>> top_5_increases = heapq.nlargest(5, increases.items(), key=lambda x: x[1])
>>>
>>> ## Display the results
>>> print("Top 5 routes with the greatest ridership increase from 2001 to 2011:")
>>> for route, increase in top_5_increases:
...     print(f"Route {route}: increased by {increase:,} rides")
...     print(f"  2001 rides: {rides_2001[route]:,}")
...     print(f"  2011 rides: {rides_2011[route]:,}")
...     print()

Nous créons d'abord deux objets Counter, rides_2001 et rides_2011, pour stocker le nombre total de passagers pour chaque itinéraire en 2001 et 2011 respectivement. Lorsque nous parcourons chaque ligne de la liste rows, nous vérifions si la date commence par '2001 -' ou '2011 -' et ajoutons les passagers au compteur approprié.

Ensuite, nous créons un dictionnaire vide increases pour stocker l'augmentation de la fréquentation pour chaque itinéraire. Nous parcourons les itinéraires uniques et calculons l'augmentation en soustrayant le nombre de passagers en 2001 du nombre de passagers en 2011 pour chaque itinéraire.

Pour trouver les 5 itinéraires avec les plus grandes augmentations, nous utilisons la fonction heapq.nlargest. Cette fonction prend le nombre d'éléments à retourner (5 dans ce cas), l'itérable (increases.items()) et une fonction clé (lambda x: x[1]) qui spécifie comment comparer les éléments.

Enfin, nous imprimons les résultats, montrant le numéro de l'itinéraire, l'augmentation de la fréquentation et le nombre de passagers en 2001 et 2011.

Cette analyse identifie quels itinéraires de bus ont connu la plus forte croissance de la fréquentation au cours de la décennie, ce qui pourrait indiquer des changements dans les modèles de population, des améliorations des services ou d'autres tendances intéressantes.

Vous pouvez étendre ces analyses de nombreuses manières. Par exemple, vous pourriez :

  • Analyser les modèles de fréquentation en fonction du jour de la semaine
  • Trouver les itinéraires dont la fréquentation diminue
  • Comparer les variations saisonnières de la fréquentation

Les techniques que vous avez apprises dans ce laboratoire fournissent une base solide pour ce type d'exploration et d'analyse de données.

Résumé

Dans ce laboratoire, vous avez appris plusieurs techniques importantes de manipulation de données en Python. Cela inclut la lecture et le traitement de données CSV en dictionnaires, l'utilisation de compréhensions de listes, d'ensembles et de dictionnaires pour la transformation de données, ainsi que l'utilisation de types de conteneurs spécialisés du module collections. Vous avez également appliqué ces compétences pour effectuer une analyse de données significative.

Ces techniques sont fondamentales pour l'analyse de données en Python et sont précieuses dans diverses situations réelles. La capacité à traiter, transformer et extraire des informations à partir de données est essentielle pour les programmeurs Python. Continuez à pratiquer avec vos propres jeux de données pour améliorer votre expertise dans l'analyse de données en Python.