web-dev-qa-db-fra.com

Quelle est la différence entre utiliser loc et utiliser uniquement des crochets pour filtrer les colonnes dans Pandas / Python?

J'ai remarqué trois méthodes pour sélectionner une colonne dans un Pandas DataFrame:

Première méthode de sélection d'une colonne à l'aide de loc:

df_new = df.loc[:, 'col1']

Deuxième méthode - semble plus simple et plus rapide:

df_new = df['col1']

Troisième méthode - la plus pratique:

df_new = df.col1

Y a-t-il une différence entre ces trois méthodes? Je ne pense pas, auquel cas je préfère utiliser la troisième méthode.

Je suis surtout curieux de savoir pourquoi il semble y avoir trois méthodes pour faire la même chose.

34
Sean McCarthy

Dans les situations suivantes, ils se comportent de la même manière:

  1. Sélection d'une seule colonne (df['A'] est le même que df.loc[:, 'A'] -> sélectionne la colonne A)
  2. Sélection d'une liste de colonnes (df[['A', 'B', 'C']] est le même que df.loc[:, ['A', 'B', 'C']] -> sélectionne les colonnes A, B et C)
  3. Découpage par lignes (df[1:3] est le même que df.iloc[1:3] -> sélectionne les lignes 1 et 2. Notez cependant que si vous découpez les lignes avec loc, au lieu de iloc, vous obtiendrez les lignes 1, 2 et 3 en supposant que vous avez un RandeIndex . Voir les détails ici .)

Toutefois, [] ne fonctionne pas dans les situations suivantes:

  1. Vous pouvez sélectionner une seule ligne avec df.loc[row_label]
  2. Vous pouvez sélectionner une liste de lignes avec df.loc[[row_label1, row_label2]]
  3. Vous pouvez découper des colonnes avec df.loc[:, 'A':'C']

Ces trois ne peuvent pas être réalisés avec []. Plus important encore, si votre sélection implique à la fois des lignes et des colonnes, l'affectation devient problématique.

df[1:3]['A'] = 5

Cela sélectionne les lignes 1 et 2, puis sélectionne la colonne "A" de l'objet renvoyé et lui attribue la valeur 5. Le problème est que l'objet renvoyé peut être une copie, ce qui peut ne pas modifier le DataFrame réel. Cela soulève SettingWithCopyWarning . La manière correcte de cette affectation est

df.loc[1:3, 'A'] = 5

Avec .loc, vous êtes assuré de modifier le DataFrame d'origine. Il vous permet également de découper des colonnes (df.loc[:, 'C':'F']), sélectionnez une seule ligne (df.loc[5]) et sélectionnez une liste de lignes (df.loc[[1, 2, 5]]).

Notez également que ces deux ne sont pas inclus dans l'API en même temps. .loc a été ajouté beaucoup plus tard en tant qu'indexeur plus puissant et explicite. Voir réponse d'unutb pour plus de détails.


Remarque: Obtention de colonnes avec [] contre . est un sujet complètement différent. . n'est là que pour convenince. Il permet uniquement d'accéder aux colonnes dont le nom est valide Python (c'est-à-dire qu'ils ne peuvent pas contenir d'espaces, ils ne peuvent pas être composés de nombres ...). Il ne peut pas être utilisé lorsque les noms entrent en conflit avec Series/DataFrame Il ne peut pas non plus être utilisé pour les colonnes non existantes (c'est-à-dire l'affectation df.a = 1 ne fonctionnera pas s'il n'y a pas de colonne a). Autre que ça, . et [] sont identiques.

34
ayhan

loc est particulièrement utile lorsque l'index n'est pas numérique (par exemple un DatetimeIndex) parce que vous pouvez obtenir lignes avec des étiquettes particulières de l'index:

df.loc['2010-05-04 07:00:00']
df.loc['2010-1-1 0:00:00':'2010-12-31 23:59:59 ','Price']

Toutefois [] est destiné à obtenir colonnes avec des noms particuliers:

df['Price']

Avec [] vous pouvez également filtrer lignes, mais c'est plus élaboré:

df[df['Date'] < datetime.datetime(2010,1,1,7,0,0)]['Price']
2
Freeman

Il semble y avoir une différence entre df.loc [] et df [] lorsque vous créez une trame de données avec plusieurs colonnes.

Vous pouvez vous référer à cette question: Existe-t-il un bon moyen de générer plusieurs colonnes en utilisant .loc?

Ici, vous ne pouvez pas générer plusieurs colonnes en utilisant df.loc [:, ['name1', 'name2']] mais vous pouvez le faire en utilisant simplement le double crochet df [['name1', 'name2']]. (Je me demande pourquoi ils se comportent différemment.)

0
Matthew Son