1743 votes

Sélection de plusieurs colonnes dans un cadre de données Pandas

J'ai des données dans différentes colonnes, mais je ne sais pas comment les extraire pour les enregistrer dans une autre variable.

index  a   b   c
1      2   3   4
2      3   4   5

Comment puis-je sélectionner 'a' , 'b' et le sauvegarder dans df1 ?

J'ai essayé

df1 = df['a':'b']
df1 = df.ix[:, 'a':'b']

Aucun ne semble fonctionner.

4 votes

Vous ne voulez jamais utiliser .ix car c'est ambigu. Utilisez .iloc o .loc si vous le devez.

1 votes

Y a-t-il un moyen de le faire sans se référer aux noms des en-têtes ? Comme dans R, je peux le faire comme ceci : > csvtable_imp_1 <- csvtable_imp[0:6] et il sélectionne le montant du delta des premières colonnes entre 0 et 6. Tout ce que j'ai eu à faire est de lire la table csv comme délimitée avec la librairie readr.

0 votes

J'ai travaillé un peu plus avec elle. J'ai trouvé quelque chose qui fonctionne comme je le voulais. La valeur par défaut est de sélectionner les nombres de caractères et non les colonnes. infile_1 = largefile_stay.ix[:,0:6]

2676voto

EMS Points 9249

Les noms des colonnes (qui sont des chaînes de caractères) ne peuvent pas être découpés de la manière dont vous avez essayé.

Ici, vous avez plusieurs options. Si vous savez, d'après le contexte, quelles variables vous voulez exclure, vous pouvez simplement renvoyer une vue de ces seules colonnes en passant une liste dans la fonction __getitem__ syntaxe (les []).

df1 = df[['a', 'b']]

Sinon, s'il est important de les indexer numériquement et non par leur nom (disons que votre code devrait le faire automatiquement sans connaître les noms des deux premières colonnes), vous pouvez faire ceci à la place :

df1 = df.iloc[:, 0:2] # Remember that Python does not slice inclusive of the ending index.

En outre, vous devez vous familiariser avec l'idée d'une vue dans un objet Pandas par rapport à une copie de cet objet. La première des méthodes ci-dessus renvoie une nouvelle copie en mémoire du sous-objet souhaité (les tranches souhaitées).

Parfois, cependant, certaines conventions d'indexation de Pandas ne permettent pas de procéder de la sorte et donnent lieu à une nouvelle variable qui fait simplement référence au même morceau de mémoire que le sous-objet ou la tranche de l'objet original. C'est ce qui se produit avec la deuxième méthode d'indexation, que vous pouvez donc modifier avec l'option .copy() pour obtenir une copie normale. Lorsque cela se produit, le fait de modifier ce que vous pensez être l'objet tranché peut parfois altérer l'objet original. Il est toujours bon d'être à l'affût de ce problème.

df1 = df.iloc[0, 0:2].copy() # To avoid the case where changing df1 also changes df

Pour utiliser iloc vous devez connaître la position des colonnes (ou indices). Comme les positions des colonnes peuvent changer, au lieu de coder les indices en dur, vous pouvez utiliser la fonction iloc ainsi que get_loc fonction de columns de l'objet dataframe pour obtenir les indices des colonnes.

{df.columns.get_loc(c): c for idx, c in enumerate(df.columns)}

Maintenant, vous pouvez utiliser ce dictionnaire pour accéder aux colonnes par les noms et en utilisant iloc .

296 votes

Note : df[['a','b']] produit une copie

1 votes

Oui, c'était implicite dans ma réponse. La partie concernant la copie n'était destinée qu'à l'usage de ix[] si vous préférez à utiliser ix[] pour quelque raison que ce soit.

1 votes

ix indexe les lignes, pas les colonnes. Je pensais que l'OP voulait des colonnes.

284voto

ayhan Points 33889

À partir de la version 0.11.0, les colonnes peut être tranché de la manière dont vous avez essayé d'utiliser la fonction .loc l'indexeur :

df.loc[:, 'C':'E']

est équivalent à

df[['C', 'D', 'E']]  # or df.loc[:, ['C', 'D', 'E']]

et renvoie des colonnes C par le biais de E .


Une démo sur un DataFrame généré aléatoirement :

import pandas as pd
import numpy as np
np.random.seed(5)
df = pd.DataFrame(np.random.randint(100, size=(100, 6)),
                  columns=list('ABCDEF'),
                  index=['R{}'.format(i) for i in range(100)])
df.head()

Out:
     A   B   C   D   E   F
R0  99  78  61  16  73   8
R1  62  27  30  80   7  76
R2  15  53  80  27  44  77
R3  75  65  47  30  84  86
R4  18   9  41  62   1  82

Pour obtenir les colonnes de C à E (notez que contrairement au découpage en nombres entiers, 'E' est inclus dans les colonnes) :

df.loc[:, 'C':'E']

Out:
      C   D   E
R0   61  16  73
R1   30  80   7
R2   80  27  44
R3   47  30  84
R4   41  62   1
R5    5  58   0
...

Le même principe s'applique à la sélection des lignes en fonction des étiquettes. Obtenez les lignes 'R6' à 'R10' à partir de ces colonnes :

df.loc['R6':'R10', 'C':'E']

Out:
      C   D   E
R6   51  27  31
R7   83  19  18
R8   11  67  65
R9   78  27  29
R10   7  16  94

.loc accepte également un tableau booléen afin que vous puissiez sélectionner les colonnes dont l'entrée correspondante dans le tableau est True . Par exemple, df.columns.isin(list('BCD')) renvoie à array([False, True, True, True, False, False], dtype=bool) - Vrai si le nom de la colonne est dans la liste ['B', 'C', 'D'] ; Faux, sinon.

df.loc[:, df.columns.isin(list('BCD'))]

Out:
      B   C   D
R0   78  61  16
R1   27  30  80
R2   53  80  27
R3   65  47  30
R4    9  41  62
R5   78   5  58
...

142voto

hobs Points 3020

En supposant que les noms de vos colonnes ( df.columns ) sont ['index','a','b','c'] alors les données que vous voulez sont dans les troisième et quatrième colonnes. Si vous ne connaissez pas leurs noms lorsque votre script s'exécute, vous pouvez faire ceci

newdf = df[df.columns[2:4]] # Remember, Python is zero-offset! The "third" entry is at slot two.

Comme le souligne EMS dans sa réponse , df.ix découpe les colonnes de manière un peu plus concise, mais la fonction .columns L'interface de découpage est peut-être plus naturelle, car elle utilise la syntaxe d'indexation/de découpage de liste unidimensionnelle de Python.

Avertissement : 'index' est un mauvais nom pour un DataFrame colonne. Ce même libellé est également utilisé pour le réel df.index un attribut Index réseau. Ainsi, votre colonne est retournée par df['index'] et l'index réel du DataFrame est retourné par df.index . Un site Index est un type particulier de Series optimisé pour la recherche des valeurs de ses éléments. Pour df.index, c'est pour rechercher des lignes par leur étiquette. C'est df.columns est également un pd.Index pour rechercher les colonnes par leurs étiquettes.

3 votes

Comme je l'ai noté dans mon commentaire ci-dessus, .ix es no juste pour les rangs. Il est destiné à un découpage général et peut être utilisé pour un découpage multidimensionnel. Il s'agit essentiellement d'une interface avec la fonction habituelle de NumPy, à savoir __getitem__ syntaxe. Cela dit, vous pouvez facilement convertir un problème de découpage en colonnes en un problème de découpage en lignes en appliquant simplement une opération de transposition, df.T . Votre exemple utilise columns[1:3] ce qui est un peu trompeur. Le résultat de columns est un Series ; faites attention à ne pas le traiter comme un tableau. De plus, vous devriez probablement le changer pour être columns[2:3] pour correspondre à votre commentaire "3ème et 4ème".

0 votes

@Mr.F : Mon [2:4] est correct. Votre [2:3] a tort. Et l'utilisation de la notation de découpage standard de Python pour générer une séquence/série n'est pas trompeuse. Mais j'aime bien votre contournement de l'interface DataFrame pour accéder au tableau numpy sous-jacent avec ix .

0 votes

Vous avez raison dans ce cas, mais ce que je voulais dire, c'est qu'en général, Le découpage en tranches avec des étiquettes dans Pandas inclut le point d'extrémité de la tranche. (ou du moins, c'était le comportement dans la plupart des versions précédentes de Pandas). Ainsi, si vous récupérez df.columns et que vous voulez le couper en tranches par étiquette alors la sémantique de la tranche serait différente de celle de la tranche suivante par position d'indice entier . Je ne l'ai certainement pas bien expliqué dans mon commentaire précédent.

96voto

zerovector Points 1178

Dans la dernière version de Pandas, il existe un moyen facile de faire exactement cela. Les noms des colonnes (qui sont des chaînes de caractères) puede à découper de la manière que vous souhaitez.

columns = ['b', 'c']
df1 = pd.DataFrame(df, columns=columns)

79voto

Wes McKinney Points 17545
In [39]: df
Out[39]: 
   index  a  b  c
0      1  2  3  4
1      2  3  4  5

In [40]: df1 = df[['b', 'c']]

In [41]: df1
Out[41]: 
   b  c
0  3  4
1  4  5

1 votes

Et si je voulais renommer la colonne, par exemple quelque chose comme : df[['b as foo', 'c as bar'] de sorte que la sortie renomme la colonne b como foo et colonne c como bar ?

6 votes

df[['b', 'c']].rename(columns = {'b' : 'foo', 'c' : 'bar'})

0 votes

Une explication s'impose. Par exemple, quel est l'essentiel ? Vous pouvez modifiez votre réponse - sans "Editer :", "Mettre à jour :", ou similaire - la réponse doit apparaître comme si elle avait été écrite aujourd'hui.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X