<jupyter_start><jupyter_text>Apprendre à connaître les structures de données de Pandas<jupyter_code><jupyter_output><empty_output><jupyter_text>Alors qu'un DataFrame 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 DataFrame et créer des objets Pandas plus petits à partir de zéro. Comprendre les objets de sérieLa structure de données la plus élémentaire de Python est la liste, qui est également un bon point de départ pour apprendre à connaître les objets `pandas.Series`. Créez un nouvel objet Series basé sur une liste:<jupyter_code>l = ['a' , 1, 'toto']
l[2]
d = { 'cle': '2', 3: 10, 'x':4}
d['cle']
d[3]
d['newdata'] = {'x':1, 'y': 2}
d
d['newdata']
import pandas as pd
revenues = pd.Series([5555, 7000, 1980])
revenues<jupyter_output><empty_output><jupyter_text>Vous avez utilisé la liste [5555, 7000, 1980] pour créer un objet Série appelé revenus. Un objet Series encapsule deux composants:* Une séquence de valeurs* Une séquence d'identifiants, qui est l'indexVous pouvez accéder à ces composants avec .values et .index, respectivement:<jupyter_code>print(revenues.index,revenues.values)
type(revenues.values)<jupyter_output><empty_output><jupyter_text>Alors que Pandas s'appuie sur NumPy, une différence significative réside dans leur indexation. Tout comme un tableau NumPy, une série Pandas possède également un index entier défini implicitement. Cet index implicite indique la position de l'élément dans la série.Cependant, une série peut également avoir un type d'index arbitraire. Vous pouvez considérer cet index explicite comme des étiquettes pour une ligne spécifique:<jupyter_code>city_revenues = pd.Series(
    [4200, 8000, 6500],
    index=["Amsterdam", "Toronto", "Tokyo"]
)
# SQL : insert ("Amsterdam", "Toronto", "Tokyo") into city_r  values  (4200, 8000, 6500)
print(city_revenues.index,city_revenues.values)<jupyter_output>Index(['Amsterdam', 'Toronto', 'Tokyo'], dtype='object') [4200 8000 6500]<jupyter_text>En fait un mode de référencement par clé:valeur<jupyter_code>city_revenues<jupyter_output><empty_output><jupyter_text>On peu utiliser les dictionnaire de Python pour initialiser une Serie<jupyter_code>city_employee_count = pd.Series({"Amsterdam": 5, "Tokyo": 8})
city_employee_count<jupyter_output><empty_output><jupyter_text>Les clés du dictionnaire deviennent l'index et les valeurs du dictionnaire sont les valeurs Series.Tout comme les dictionnaires, Series prend également en charge .keys () et le mot-clé in:<jupyter_code>print(city_employee_count.keys(),city_employee_count.values,city_employee_count.index)<jupyter_output>Index(['Amsterdam', 'Tokyo'], dtype='object') [5 8] Index(['Amsterdam', 'Tokyo'], dtype='object')<jupyter_text>Comprendre les objets DataFrameBien qu'une série soit 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 l’ensemble de données nba, qui comprend 23 colonnes, la bibliothèque Pandas Python a plus à offrir avec son DataFrame. Cette structure de données est une séquence d'objets Series qui partagent le même index.Si vous avez suivi les exemples de séries, vous devriez déjà avoir deux objets de série avec des villes comme clés:* city_revenues* city_employee_countVous pouvez combiner ces objets dans un DataFrame en fournissant un dictionnaire dans le constructeur. Les clés du dictionnaire deviendront les noms de colonne et les valeurs doivent contenir les objets Series:<jupyter_code>print('revenues', city_revenues,'employé', city_employee_count, sep='\n----\n')<jupyter_output>revenues
----
Amsterdam    4200
Toronto      8000
Tokyo        6500
dtype: int64
----
employé
----
Amsterdam    5
Tokyo        8
dtype: int64<jupyter_text><jupyter_code>city_data = pd.DataFrame({
    "revenue": city_revenues,
    "employee_count": city_employee_count
})
city_data<jupyter_output><empty_output><jupyter_text>Reamarque ce qui se passe pour Torento<jupyter_code>city_data.index
city_data.values<jupyter_output><empty_output><jupyter_text>On peut également désigner les 2 dimensions d'un DataFrame comme des axes:<jupyter_code>print(city_data.axes)
print(city_data.axes[0],city_data.axes[1])<jupyter_output>[Index(['Amsterdam', 'Tokyo', 'Toronto'], dtype='object'), Index(['revenue', 'employee_count'], dtype='object')]
Index(['Amsterdam', 'Tokyo', 'Toronto'], dtype='object') Index(['revenue', 'employee_count'], dtype='object')<jupyter_text>Un DataFrame est également une structure de données de type dictionnaire, il prend donc également en charge .keys () et le mot clé in. Cependant, pour un DataFrame, ceux-ci ne sont pas liés à l'index, mais aux colonnes:<jupyter_code>city_data.keys()<jupyter_output><empty_output><jupyter_text>Revenons à notre exemple nba<jupyter_code>nba = pd.read_csv('https://github.com/fivethirtyeight/data/raw/master/nba-elo/nbaallelo.csv')
type(nba)
nba.index
nba.axes
nba.keys()<jupyter_output><empty_output><jupyter_text>Lorsque vous utilisez ces méthodes pour répondre à des questions sur votre ensemble de données, assurez-vous de garder à l'esprit si vous travaillez avec une série ou un DataFrame afin que votre interprétation soit précise.  Accès aux éléments de la sérieDans la section ci-dessus, vous avez créé une série Pandas basée sur une liste Python et comparé les deux structures de données. Vous avez vu comment un objet Series est similaire à des listes et des dictionnaires de plusieurs manières. Une autre similitude est que vous pouvez également utiliser l'opérateur d'indexation ([]) pour Series.Vous apprendrez également à utiliser deux méthodes d'accès spécifiques à Pandas:* .loc* .ilocVous 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'indexationRappelez-vous qu'une série a deux indices:1. Un index positionnel ou implicite, qui est toujours un RangeIndex2. Une étiquette ou un index explicite, qui peut contenir tous les objets hachablesEnsuite, revisitez l'objet city_revenues:<jupyter_code>city_revenues
city_revenues['Amsterdam']
city_revenues[0]
# Vous pouvez également utiliser des indices et des tranches négatifs, comme vous le feriez pour une liste:
city_revenues[-1]
city_revenues[1:]
city_revenues["Toronto":]<jupyter_output><empty_output><jupyter_text>utilisation loc et ilocL'opérateur d'indexation ([]) est pratique, mais il y a une mise en garde. Et si les étiquettes sont également des nombres? Supposons que vous deviez travailler avec un objet Series comme celui-ci:<jupyter_code>import pandas as pd
colors = pd.Series(
    ["red", "purple", "blue", "green", "yellow"],
    index=[1, 2, 3, 5, 8]
)
colors<jupyter_output><empty_output><jupyter_text>Que reviendront les coulor[1]? Pour un index positionnel, les coulor[1] sont "purple". Cependant, si vous passez par l'index des étiquettes, alors colors[1] fait référence au "rouge".La bonne nouvelle est que vous n’avez pas à le découvrir! Au lieu de cela, pour éviter toute confusion, la bibliothèque Pandas Python fournit deux méthodes d'accès aux données:1. .loc fait référence à l'index de l'étiquette (la clé).2. .iloc fait référence à l'index de position.Ces méthodes d'accès aux données sont beaucoup plus lisibles:<jupyter_code>print(colors)
print(f'loc[1]={colors.loc[1]}, iloc[1]={colors.iloc[1]}')<jupyter_output>1       red
2    purple
3      blue
5     green
8    yellow
dtype: object
loc[1]=red, iloc[1]=purple<jupyter_text>iloc position, loc clé![loc iloc](https://github.com/lipug/datascience/raw/main/pandasIntro/loc_iloc.png) .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 présentent une différence importante. Alors que .iloc exclut l'élément de fermeture, .loc l'inclut. Jetez un œil à ce bloc de code:<jupyter_code>colors.loc[3:8]
#pas ceci
# colors.loc[-1]

# Mais cela
colors.iloc[-1]<jupyter_output><empty_output><jupyter_text>Accès aux éléments DataFrame (requêtes)Puisqu'un DataFrame se compose d'objets Series, vous pouvez utiliser les mêmes outils pour accéder à ses éléments. La différence cruciale est la dimension supplémentaire du DataFrame. Vous utiliserez l'opérateur d'indexation pour les colonnes et les méthodes d'accès .loc et .iloc sur les lignes.Utilisation de l'opérateur d'indexationSi vous considérez un DataFrame comme un dictionnaire dont les valeurs sont Series, alors il est logique que vous puissiez accéder à ses colonnes avec l'opérateur d'indexation:<jupyter_code>city_revenues = pd.Series(
    [4200, 8000, 6500],
    index=["Amsterdam", "Toronto", "Tokyo"]
)

city_employee_count = pd.Series({"Amsterdam": 5, "Tokyo": 8})

city_data = pd.DataFrame({
    "revenue": city_revenues,
    "employee_count": city_employee_count
})
city_data["revenue"]
type(city_data["revenue"])<jupyter_output><empty_output><jupyter_text>Ici, vous utilisez l'opérateur d'indexation pour sélectionner la colonne intitulée "revenus".INTERESSANT: Si le nom de la colonne est une chaîne, vous pouvez également utiliser un accès de style attribut avec la notation par points:<jupyter_code>city_data.revenue
city_data.shape
city_data.describe()
city_data.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
Index: 3 entries, Amsterdam to Toronto
Data columns (total 2 columns):
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   revenue         3 non-null      int64  
 1   employee_count  2 non-null      float64
dtypes: float64(1), int64(1)
memory usage: 180.0+ bytes<jupyter_text>revenons a des exemples plus conséquents<jupyter_code>nba = pd.read_csv('https://github.com/fivethirtyeight/data/raw/master/nba-elo/nbaallelo.csv')
type(nba)
nba.iloc[-1]<jupyter_output><empty_output><jupyter_text>Pour un DataFrame, les méthodes d'accès aux données .loc et .iloc acceptent également un deuxième paramètre. Alors que le premier paramètre sélectionne les lignes en fonction des indices, le second paramètre sélectionne les colonnes. Vous pouvez utiliser ces paramètres ensemble pour sélectionner un sous-ensemble de lignes et de colonnes dans votre DataFrame:<jupyter_code>nba.loc[5555:5559, ["fran_id", "opp_fran", "pts", "opp_pts"]]<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09291141675483312, 'fraction_numerical': 0.016350870443397135, 'mean_word_length': 5.964501004688547, 'pattern_counts': {'":': 9, '<': 80, '<?xml version=': 0, '>': 80, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '21', 'dir': 'jupyter-structured-clean-dedup', 'id': '128104', 'license': 'MIT', 'n_tokens_mistral': 3646, 'n_tokens_neox': 3559, 'n_words': 1119, 'path': 'Notebook/Data/DS02_Pandas_structureDonnees.ipynb', 'repo_name': 'opentrainingcamp/python', 'size': '10397'}