web-dev-qa-db-fra.com

Pour Pandas DataFrame, quelle est la différence entre l'utilisation de crochets ou de points pour accéder à une colonne?

c'est à dire.:

import pandas

d = {'col1': 2, 'col2': 2.5}
df = pandas.DataFrame(data=d, index=[0])

print(df['col2'])
print(df.col2)

La sortie est la même.

Cette réponse s'applique-t-elle à ce cas?

Quelle est la différence entre les notations entre crochets et points en Python?

40
Alberto Segundo

La "notation par points", c'est-à-dire df.col2 est le accès aux attributs qui est présenté par commodité.

Vous pouvez accéder à un index sur une série, une colonne sur un DataFrame et un élément sur un panneau directement en tant qu'attribut:

df['col2'] fait de même: il renvoie un pd.Series de la colonne.

Quelques mises en garde concernant l'accès aux attributs:

  • vous ne pouvez pas ajouter de colonne (df.new_col = x ne fonctionnera pas, pire: il silencieusement créera en fait un nouvel attribut plutôt qu'une colonne - pensez au patch de singe ici)
  • cela ne fonctionnera pas si vous avez des espaces dans le nom de la colonne ou si le nom de la colonne est un entier.
37
Julien Marrec

Ils sont les mêmes tant que vous accédez à une seule colonne avec un nom simple, mais vous pouvez faire plus avec la notation entre crochets. Vous ne pouvez utiliser que df.col si le nom de la colonne est un identifiant valide Python (par exemple, ne contient pas d'espaces et d'autres éléments de ce type). En outre, vous pouvez rencontrer des surprises si le nom de votre colonne se heurte à un pandas nom de la méthode (comme sum). Avec des crochets, vous pouvez sélectionner plusieurs colonnes (par exemple, df[['col1', 'col2']]) ou ajoutez une nouvelle colonne (df['newcol'] = ...), ce qui ne peut pas être fait avec un accès par points.

L'autre question à laquelle vous avez lié s'applique, mais c'est une question beaucoup plus générale. Python définissent comment les . et [] les opérateurs s'appliquent à eux. Pandas DataFrames ont choisi de les rendre identiques pour ce cas limité d'accès à des colonnes uniques, avec les mises en garde décrites ci-dessus.

14
BrenBarn

Réponse courte aux différences:

  • [] l'indexation (accès entre crochets) a toutes les fonctionnalités pour fonctionner sur les données de la colonne DataFrame.
  • Alors que l'accès aux attributs (accès par points) est principalement destiné à l'accès aux données de colonne DataFrame existantes, mais a parfois ses limites (par exemple, noms de colonnes spéciales, création d'un nouveau colonne).

Plus d'explications, Seires et DataFrame sont des classes de base et des structures de données dans les pandas, et bien sûr, ce sont des classes Python aussi, donc il y a une distinction mineure lors de l'accès aux attributs entre pandas DataFrame et normal Python objets. Mais c'est bien documenté et peut être facilement compris. Juste quelques points à noter:

  1. En Python, les utilisateurs peuvent ajouter dynamiquement leurs propres attributs de données à un objet d'instance en utilisant l'accès aux attributs.

    >>> class Dog(object):
    ...     pass
    >>> dog = Dog()
    >>> vars(dog)
    {}
    >>> superdog = Dog()
    >>> vars(superdog)
    {}
    >>> dog.legs = 'I can run.'
    >>> superdog.wings = 'I can fly.'
    >>> vars(dog)
    {'legs': 'I can run.'}
    >>> vars(superdog)
    {'wings': 'I can fly.'}
    
  2. Dans les pandas, index et colonne sont étroitement liés à la structure des données, vous pouvez accéder un index sur une série, une colonne sur un DataFrame comme attribut .

    >>> import pandas as pd
    >>> import numpy as np
    >>> data = np.random.randint(low=0, high=10, size=(2,2))
    >>> df = pd.DataFrame(data, columns=['a', 'b'])
    >>> df
       a  b
    0  7  6
    1  5  8
    >>> vars(df)
    {'_is_copy': None, 
     '_data': BlockManager
        Items: Index(['a', 'b'], dtype='object')
        Axis 1: RangeIndex(start=0, stop=2, step=1)
        IntBlock: slice(0, 2, 1), 2 x 2, dtype: int64,
     '_item_cache': {}}
    
  3. Mais, pandas est principalement un moyen pratique pour lire et modifier un élément existant d'une série ou d'une colonne de un DataFrame.

    >>> df.a
    0    7
    1    5
    Name: a, dtype: int64
    >>> df.b = [1, 1]
    >>> df
       a  b
    0  7  1
    1  5  1
    
  4. Et, la commodité est un compromis pour une fonctionnalité complète. Par exemple. vous pouvez créer un objet DataFrame avec des noms de colonne ['space bar', '1', 'loc', 'min', 'index'], mais vous ne pouvez pas y accéder en tant qu'attribut, car ce n'est pas un identifiant valide Python 1, space bar ou entre en conflit avec un nom de méthode existant.

    >>> data = np.random.randint(0, 10, size=(2, 5))
    >>> df_special_col_names = pd.DataFrame(data, columns=['space bar', '1', 'loc', 'min', 'index'])
    >>> df_special_col_names
       space bar  1  loc  min  index
    0          4  4    4    8      9
    1          3  0    1    2      3
    
  5. Dans ces cas, le .loc, .iloc et [] l'indexation est de la manière définie pour accéder/utiliser pleinement l'index et les colonnes des objets Series et DataFrame.

    >>> df_special_col_names['space bar']
    0    4
    1    3
    Name: space bar, dtype: int64
    >>> df_special_col_names.loc[:, 'min']
    0    8
    1    2
    Name: min, dtype: int64
    >>> df_special_col_names.iloc[:, 1]
    0    4
    1    0
    Name: 1, dtype: int64
    
  6. Une autre différence importante est lors de la création d'une nouvelle colonne pour DataFrame. Comme vous pouvez le voir, df.c = df.a + df.b juste créé un nouvel attribut à côté de la structure de données principale , donc à partir de la version 0.21.0 et plus tard, ce comportement fera monter un UserWarning (plus de silence).

    >>> df
       a  b
    0  7  1
    1  5  1
    >>> df.c = df.a + df.b
    __main__:1: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
    >>> df['d'] = df.a + df.b
    >>> df
       a  b  d
    0  7  1  8
    1  5  1  6
    >>> df.c
    0    8
    1    6
    dtype: int64
    >>> vars(df)
    {'_is_copy': None, 
     '_data': 
        BlockManager
        Items: Index(['a', 'b', 'd'], dtype='object')
        Axis 1: RangeIndex(start=0, stop=2, step=1)
        IntBlock: slice(0, 2, 1), 2 x 2, dtype: int64
        IntBlock: slice(2, 3, 1), 1 x 2, dtype: int64, 
     '_item_cache': {},
     'c': 0    8
          1    6
          dtype: int64}
    
  7. Enfin, pour créer une nouvelle colonne pour DataFrame, n'utilisez jamais l'accès aux attributs , la bonne façon est de utiliser soit [] ou .loc indexation :

    >>> df
       a  b
    0  7  6
    1  5  8
    >>> df['c'] = df.a + df.b 
    >>> # OR
    >>> df.loc[:, 'c'] = df.a + df.b
    >>> df # c is an new added column
       a  b   c
    0  7  6  13
    1  5  8  13
    
2
YaOzI