Obtenir la liste des en-têtes de colonne Pandas DataFrame

1017

Je veux obtenir une liste des en-têtes de colonne d'un pandas DataFrame. Le DataFrame proviendra de l'entrée utilisateur, donc je ne saurai pas combien de colonnes il y aura ou comment elles seront appelées.

Par exemple, si on me donne un DataFrame comme ceci:

>>> my_dataframe
    y  gdp  cap
0   1    2    5
1   2    3    9
2   8    7    2
3   3    4    7
4   6    7    7
5   4    8    3
6   8    2    8
7   9    9   10
8   6    6    4
9  10   10    7

Je voudrais obtenir une liste comme celle-ci:

>>> header_list
['y', 'gdp', 'cap']
natsuki_2002
la source
A partir de python3.5 +, vous pouvez utiliser [*df]plus list(df)ou df.columns.tolist(), c'est grâce aux généralisations de décompression (PEP 448) .
cs95 Il y a

Réponses:

1648

Vous pouvez obtenir les valeurs sous forme de liste en faisant:

list(my_dataframe.columns.values)

Vous pouvez également simplement utiliser: (comme indiqué dans la réponse d'Ed Chum ):

list(my_dataframe)
Simeon Visser
la source
42
Pourquoi ce document n'a-t- il pas columnsd'attribut?
Tjorriemorrie
@Tjorriemorrie: Je ne suis pas sûr, cela peut être lié à la façon dont ils génèrent automatiquement leur documentation. Il est mentionné dans d'autres endroits cependant: pandas.pydata.org/pandas-docs/stable/…
Simeon Visser
8
Je m'attendrais à quelque chose comme ça df.column_names(). Cette réponse est-elle toujours exacte ou obsolète?
alvas
1
@alvas, il existe plusieurs autres façons de le faire (voir les autres réponses sur cette page) mais pour autant que je sache, il n'y a pas de méthode sur la trame de données directement pour produire la liste.
Simeon Visser
19
Surtout, cela préserve l'ordre des colonnes.
WindChimes
405

Il existe une méthode intégrée qui est la plus performante:

my_dataframe.columns.values.tolist()

.columnsrenvoie un index, .columns.valuesretourne un tableau et cela a une fonction d'aide .tolistpour retourner une liste.

Si les performances ne sont pas aussi importantes pour vous, les Indexobjets définissent une .tolist()méthode que vous pouvez appeler directement:

my_dataframe.columns.tolist()

La différence de performances est évidente:

%timeit df.columns.tolist()
16.7 µs ± 317 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit df.columns.values.tolist()
1.24 µs ± 12.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Pour ceux qui détestent taper, vous pouvez simplement appeler listsur df, comme ceci:

list(df)
EdChum
la source
4
Je n'ai pas rejeté le vote, mais je veux expliquer: ne vous fiez pas aux détails de mise en œuvre, utilisez "l'interface publique" de DataFrame. Pensez à la beauté de df.keys ()
Sascha Gottfried
3
@SaschaGottfried la mise en œuvre de l' DataFrameitérable n'a pas changé depuis le premier jour: pandas.pydata.org/pandas-docs/stable/basics.html#iteration . L'itérable renvoyé par un DataFrame a toujours été les colonnes, ce qui fait que le comportement for col in df:devrait toujours se comporter de la même manière, à moins que les développeurs ne le list(df)fassent et qu'il devrait toujours être une méthode valide. Notez que df.keys()c'est appeler dans l'implémentation interne de la structure de type dict renvoyant les clés qui sont les colonnes. Les downvotes inexplicables sont les dommages collatéraux à prévoir sur SO donc ne vous inquiétez pas
EdChum
Je faisais référence aux détails d'implémentation de l' columnsattribut. Il y a une heure, j'ai lu que Law of Demeter faisait la promotion que l'appelant ne devrait pas dépendre de la navigation dans le modèle d'objet interne. list(df)effectue une conversion de type explicite. Effet secondaire notable: le temps d'exécution et la consommation de mémoire augmentent avec la df.keys()méthode de taille de trame de données fait partie de la nature dict-dict d'un DataFrame. Fait notable: le temps d'exécution de df.keys()est plutôt constant quelle que soit la taille de la trame de données - une partie de la responsabilité des développeurs de pandas.
Sascha Gottfried
1
@SaschaGottfried Je peux ajouter ceci à ma réponse et vous remercier car personne d'autre ne l'a inclus
EdChum
1
Je peux voir la valeur dans la réponse donnée ainsi que dans les commentaires - pas besoin de changer quoi que ce soit.
Sascha Gottfried
89

A fait quelques tests rapides, et sans surprise la version intégrée utilisant dataframe.columns.values.tolist()est la plus rapide:

In [1]: %timeit [column for column in df]
1000 loops, best of 3: 81.6 µs per loop

In [2]: %timeit df.columns.values.tolist()
10000 loops, best of 3: 16.1 µs per loop

In [3]: %timeit list(df)
10000 loops, best of 3: 44.9 µs per loop

In [4]: % timeit list(df.columns.values)
10000 loops, best of 3: 38.4 µs per loop

(J'aime quand même vraiment list(dataframe), alors merci EdChum!)

tegan
la source
47

C'est encore plus simple (par pandas 0.16.0):

df.columns.tolist()

vous donnera les noms des colonnes dans une belle liste.

fixxxer
la source
37
>>> list(my_dataframe)
['y', 'gdp', 'cap']

Pour répertorier les colonnes d'une trame de données en mode débogueur, utilisez une compréhension de liste:

>>> [c for c in my_dataframe]
['y', 'gdp', 'cap']

Soit dit en passant, vous pouvez obtenir une liste triée simplement en utilisant sorted:

>>> sorted(my_dataframe)
['cap', 'gdp', 'y']
Alexandre
la source
Cela ne list(df)fonctionnerait-il qu'avec des trames de données à incrémentation automatique? Ou cela fonctionne-t-il pour toutes les trames de données?
alvas
2
Devrait fonctionner pour tous. Cependant, lorsque vous êtes dans le débogueur, vous devez utiliser une compréhension de liste [c for c in df].
Alexander
25

Surpris de ne pas l'avoir vu jusqu'à présent, je vais donc laisser cela ici.

Déballage Iterable étendu (python3.5 +): [*df]et amis

Des généralisations de déballage (PEP 448) ont été introduites avec Python 3.5. Ainsi, les opérations suivantes sont toutes possibles.

df = pd.DataFrame('x', columns=['A', 'B', 'C'], index=range(5))
df

   A  B  C
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x
4  x  x  x 

Si vous voulez un list....

[*df]
# ['A', 'B', 'C']

Ou, si vous en voulez un set,

{*df}
# {'A', 'B', 'C'}

Ou, si vous en voulez un tuple,

*df,  # Please note the trailing comma
# ('A', 'B', 'C')

Ou, si vous souhaitez stocker le résultat quelque part,

*cols, = df  # A wild comma appears, again
cols
# ['A', 'B', 'C']

... si vous êtes le genre de personne qui convertit le café en sons de frappe, eh bien, cela va consommer votre café plus efficacement;)

PS: si les performances sont importantes, vous voudrez abandonner les solutions ci-dessus en faveur de

df.columns.to_numpy().tolist()
# ['A', 'B', 'C']

Ceci est similaire à la réponse d'Ed Chum , mais mis à jour pour la version 0.24 où il .to_numpy()est préférable à l'utilisation de .values. Voir cette réponse (par moi) pour plus d'informations.

Vérification visuelle
Depuis que j'ai vu cela discuté dans d'autres réponses, vous pouvez utiliser le déballage itérable (pas besoin de boucles explicites).

print(*df)
A B C

print(*df, sep='\n')
A
B
C

Critique des autres méthodes

N'utilisez pas de forboucle explicite pour une opération qui peut être effectuée sur une seule ligne (les compréhensions de liste sont correctes).

Ensuite, l'utilisation sorted(df) ne conserve pas l'ordre d'origine des colonnes. Pour cela, vous devez utiliser à la list(df)place.

Ensuite, list(df.columns)et list(df.columns.values)sont de mauvaises suggestions (à partir de la version actuelle, v0.24). Les deux Index(retour de df.columns) et les tableaux numpy (retournées par df.columns.values) définissent la .tolist()méthode qui est plus rapide et plus idiomatiques.

Enfin, la listification, c'est-à-dire list(df)ne doit être utilisée que comme une alternative concise aux méthodes susmentionnées pour python <= 3.4 lorsque le déballage étendu n'est pas disponible.

cs95
la source
24

C'est disponible en tant que my_dataframe.columns.

BrenBarn
la source
1
Et explicitement comme une liste parheader_list = list(my_dataframe.columns)
yeliabsalohcin
^ Ou mieux encore: df.columns.tolist().
cs95
18

C'est intéressant mais df.columns.values.tolist()c'est presque 3 fois plus rapide alors df.columns.tolist()mais je pensais que ce sont les mêmes:

In [97]: %timeit df.columns.values.tolist()
100000 loops, best of 3: 2.97 µs per loop

In [98]: %timeit df.columns.tolist()
10000 loops, best of 3: 9.67 µs per loop
Anton Protopopov
la source
2
Les délais ont déjà été couverts dans cette réponse . La raison de cet écart est que .valuesrenvoie le tableau numpy sous-jacent, et faire quelque chose avec numpy est presque toujours plus rapide que de faire la même chose avec pandas directement.
cs95
17

Un DataFrame suit la convention de type dict consistant à itérer sur les «clés» des objets.

my_dataframe.keys()

Créer une liste de clés / colonnes - méthode objet to_list()et manière pythonique

my_dataframe.keys().to_list()
list(my_dataframe.keys())

L'itération de base sur un DataFrame renvoie des étiquettes de colonne

[column for column in my_dataframe]

Ne convertissez pas un DataFrame en liste, juste pour obtenir les étiquettes de colonne. N'arrêtez pas de penser en recherchant des exemples de code pratiques.

xlarge = pd.DataFrame(np.arange(100000000).reshape(10000,10000))
list(xlarge) #compute time and memory consumption depend on dataframe size - O(N)
list(xlarge.keys()) #constant time operation - O(1)
Sascha Gottfried
la source
2
Mes tests montrent que df.columnsc'est beaucoup plus rapide que df.keys(). Je ne sais pas pourquoi ils ont à la fois une fonction et un attribut pour la même chose (eh bien, ce n'est pas la première fois que je vois 10 façons différentes de faire quelque chose dans les pandas).
cs95
1
L'intention de ma réponse était de montrer quelques façons d'interroger les étiquettes de colonne à partir d'un DataFrame et de mettre en évidence un anti-modèle de performances. Néanmoins, j'aime vos commentaires et j'ai voté pour votre réponse récente - car ils apportent de la valeur du point de vue de l'ingénierie logicielle.
Sascha Gottfried
14

Dans le cahier

Pour l'exploration de données dans le bloc-notes IPython, ma méthode préférée est la suivante:

sorted(df)

Ce qui produira une liste alphabétique facile à lire.

Dans un référentiel de code

Dans le code, je trouve cela plus explicite à faire

df.columns

Parce qu'il dit aux autres qui lisent votre code ce que vous faites.

firelynx
la source
sorted(df)change l'ordre. Utiliser avec précaution.
cs95
@coldspeed Je le mentionne cependant "ce qui produira une liste alphabétique facile à lire."
firelynx le
9
%%timeit
final_df.columns.values.tolist()
948 ns ± 19.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
list(final_df.columns)
14.2 µs ± 79.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
list(final_df.columns.values)
1.88 µs ± 11.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
final_df.columns.tolist()
12.3 µs ± 27.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
list(final_df.head(1).columns)
163 µs ± 20.6 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
rohit singh
la source
3

comme l'a répondu Simeon Visser ... vous pourriez faire

list(my_dataframe.columns.values) 

ou

list(my_dataframe) # for less typing.

Mais je pense que la plupart du sweet spot est:

list(my_dataframe.columns)

C'est explicite, en même temps pas inutilement long.

Vivek
la source
"C'est explicite, en même temps pas inutilement long." Je ne suis pas d'accord. L'appel listn'a de mérite que si vous l'appelez dfdirectement (par exemple, la concision). L'accès à l' .columnsattribut renvoie un Indexobjet qui a une tolist()méthode définie dessus, et l'appel qui est plus idiomatique que listant le Index. Mélanger des idiomes juste pour être complet n'est pas une bonne idée. Il en va de même pour lister le tableau que vous obtenez .values.
cs95
3

Pour une vérification visuelle rapide et nette, essayez ceci:

for col in df.columns:
    print col
Joseph True
la source
3

Cela nous donne les noms des colonnes dans une liste:

list(my_dataframe.columns)

Une autre fonction appelée tolist () peut également être utilisée:

my_dataframe.columns.tolist()
Harikrishna
la source
Cela a déjà été traité dans d'autres réponses. Votre première solution mélange également des idiomes, ce qui n'est pas une bonne idée. Voir mon commentaire sous une autre réponse.
cs95
2

Je pense que la question mérite des explications supplémentaires.

Comme l'a noté @fixxxer, la réponse dépend de la version pandas que vous utilisez dans votre projet. Que vous pouvez obtenir avec la pd.__version__commande.

Si vous êtes pour une raison comme moi (sur Debian Jessie, j'utilise 0.14.1) en utilisant une version plus ancienne de pandas que 0.16.0, alors vous devez utiliser:

df.keys().tolist()car il n'y a pas encore de df.columnsméthode implémentée.

L'avantage de cette méthode de touches est qu'elle fonctionne même dans les nouvelles versions de pandas, donc elle est plus universelle.

StefanK
la source
Le con de keys () est qu'il s'agit d'un appel de fonction plutôt que d'une recherche d'attribut, donc ça va toujours être plus lent. Bien sûr, avec des accès à temps constant, personne ne se soucie vraiment de ces différences, mais je pense qu'il vaut la peine de mentionner de toute façon; df.columns est désormais un idiome plus universellement accepté pour accéder aux en-têtes.
cs95
1
n = []
for i in my_dataframe.columns:
    n.append(i)
print n
user21988
la source
6
veuillez le remplacer par une liste de compréhension.
Sascha Gottfried
4
changer vos 3 premières lignes en[n for n in dataframe.columns]
Anton Protopopov
Pourquoi voudriez-vous passer par tous ces ennuis pour une opération que vous pouvez facilement faire en une seule ligne?
cs95
0

Même si la solution fournie ci-dessus est agréable. Je m'attendrais également à ce que quelque chose comme frame.column_names () soit une fonction dans pandas, mais comme ce n'est pas le cas, il serait peut-être bien d'utiliser la syntaxe suivante. Il préserve en quelque sorte le sentiment que vous utilisez les pandas de manière appropriée en appelant la fonction "tolist": frame.columns.tolist ()

frame.columns.tolist() 
Igor Jakovljevic
la source
0

Si le DataFrame possède un index ou un multi-index et que vous souhaitez que ceux-ci soient également inclus en tant que noms de colonne:

names = list(filter(None, df.index.names + df.columns.values.tolist()))

Il évite d'appeler reset_index () qui a un impact de performance inutile pour une opération aussi simple.

J'ai eu besoin de cela plus souvent parce que je transfère des données à partir de bases de données où l'index de la trame de données correspond à une clé primaire / unique, mais n'est vraiment qu'une autre "colonne" pour moi. Il serait probablement logique pour les pandas d'avoir une méthode intégrée pour quelque chose comme ça (totalement possible, je l'ai raté).

totalhack
la source
-1

Cette solution répertorie toutes les colonnes de votre objet my_dataframe:

print(list(my_dataframe))
Sunitha G
la source