web-dev-qa-db-fra.com

Comment changer l'ordre des colonnes DataFrame?

J'ai le suivant DataFrame (df):

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.Rand(10, 5))

J'ajoute plus de colonne (s) par affectation:

df['mean'] = df.mean(1)

Comment puis-je déplacer la colonne mean vers l’avant, c’est-à-dire la définir comme première colonne en conservant l’ordre des autres colonnes?

665
Timmie

Un moyen simple serait de réaffecter le cadre de données avec une liste des colonnes, réorganisée en fonction des besoins.

Voici ce que vous avez maintenant:

In [6]: df
Out[6]:
          0         1         2         3         4      mean
0  0.445598  0.173835  0.343415  0.682252  0.582616  0.445543
1  0.881592  0.696942  0.702232  0.696724  0.373551  0.670208
2  0.662527  0.955193  0.131016  0.609548  0.804694  0.632596
3  0.260919  0.783467  0.593433  0.033426  0.512019  0.436653
4  0.131842  0.799367  0.182828  0.683330  0.019485  0.363371
5  0.498784  0.873495  0.383811  0.699289  0.480447  0.587165
6  0.388771  0.395757  0.745237  0.628406  0.784473  0.588529
7  0.147986  0.459451  0.310961  0.706435  0.100914  0.345149
8  0.394947  0.863494  0.585030  0.565944  0.356561  0.553195
9  0.689260  0.865243  0.136481  0.386582  0.730399  0.561593

In [7]: cols = df.columns.tolist()

In [8]: cols
Out[8]: [0L, 1L, 2L, 3L, 4L, 'mean']

Réorganisez cols comme vous le souhaitez. Voici comment j'ai déplacé le dernier élément à la première position:

In [12]: cols = cols[-1:] + cols[:-1]

In [13]: cols
Out[13]: ['mean', 0L, 1L, 2L, 3L, 4L]

Ensuite, réorganisez le dataframe comme ceci:

In [16]: df = df[cols]  #    OR    df = df.ix[:, cols]

In [17]: df
Out[17]:
       mean         0         1         2         3         4
0  0.445543  0.445598  0.173835  0.343415  0.682252  0.582616
1  0.670208  0.881592  0.696942  0.702232  0.696724  0.373551
2  0.632596  0.662527  0.955193  0.131016  0.609548  0.804694
3  0.436653  0.260919  0.783467  0.593433  0.033426  0.512019
4  0.363371  0.131842  0.799367  0.182828  0.683330  0.019485
5  0.587165  0.498784  0.873495  0.383811  0.699289  0.480447
6  0.588529  0.388771  0.395757  0.745237  0.628406  0.784473
7  0.345149  0.147986  0.459451  0.310961  0.706435  0.100914
8  0.553195  0.394947  0.863494  0.585030  0.565944  0.356561
9  0.561593  0.689260  0.865243  0.136481  0.386582  0.730399
691
Aman

Vous pouvez aussi faire quelque chose comme ça:

df = df[['mean', '0', '1', '2', '3']]

Vous pouvez obtenir la liste des colonnes avec:

cols = list(df.columns.values)

La sortie produira:

['0', '1', '2', '3', 'mean']

... qui est ensuite facile à réorganiser manuellement avant de le laisser tomber dans la première fonction

331
freddygv

Attribuez simplement les noms des colonnes dans l'ordre de votre choix:

In [39]: df
Out[39]: 
          0         1         2         3         4  mean
0  0.172742  0.915661  0.043387  0.712833  0.190717     1
1  0.128186  0.424771  0.590779  0.771080  0.617472     1
2  0.125709  0.085894  0.989798  0.829491  0.155563     1
3  0.742578  0.104061  0.299708  0.616751  0.951802     1
4  0.721118  0.528156  0.421360  0.105886  0.322311     1
5  0.900878  0.082047  0.224656  0.195162  0.736652     1
6  0.897832  0.558108  0.318016  0.586563  0.507564     1
7  0.027178  0.375183  0.930248  0.921786  0.337060     1
8  0.763028  0.182905  0.931756  0.110675  0.423398     1
9  0.848996  0.310562  0.140873  0.304561  0.417808     1

In [40]: df = df[['mean', 4,3,2,1]]

Maintenant, la colonne 'méchante' apparaît à l'avant:

In [41]: df
Out[41]: 
   mean         4         3         2         1
0     1  0.190717  0.712833  0.043387  0.915661
1     1  0.617472  0.771080  0.590779  0.424771
2     1  0.155563  0.829491  0.989798  0.085894
3     1  0.951802  0.616751  0.299708  0.104061
4     1  0.322311  0.105886  0.421360  0.528156
5     1  0.736652  0.195162  0.224656  0.082047
6     1  0.507564  0.586563  0.318016  0.558108
7     1  0.337060  0.921786  0.930248  0.375183
8     1  0.423398  0.110675  0.931756  0.182905
9     1  0.417808  0.304561  0.140873  0.310562
280
fixxxer
112
Wes McKinney

Dans ton cas,

df = df.reindex(columns=['mean',0,1,2,3,4])

fera exactement ce que vous voulez.

Dans mon cas (forme générale):

df = df.reindex(columns=sorted(df.columns))
df = df.reindex(columns=(['opened'] + list([a for a in df.columns if a != 'opened']) ))
81
Alvaro Joao

À partir d'août 2018:

Si vos noms de colonne sont trop longs à taper, vous pouvez spécifier le nouvel ordre à l'aide d'une liste d'entiers avec les positions:

Les données:

          0         1         2         3         4      mean
0  0.397312  0.361846  0.719802  0.575223  0.449205  0.500678
1  0.287256  0.522337  0.992154  0.584221  0.042739  0.485741
2  0.884812  0.464172  0.149296  0.167698  0.793634  0.491923
3  0.656891  0.500179  0.046006  0.862769  0.651065  0.543382
4  0.673702  0.223489  0.438760  0.468954  0.308509  0.422683
5  0.764020  0.093050  0.100932  0.572475  0.416471  0.389390
6  0.259181  0.248186  0.626101  0.556980  0.559413  0.449972
7  0.400591  0.075461  0.096072  0.308755  0.157078  0.207592
8  0.639745  0.368987  0.340573  0.997547  0.011892  0.471749
9  0.050582  0.714160  0.168839  0.899230  0.359690  0.438500

Exemple générique:

new_order = [3,2,1,4,5,0]
print(df[df.columns[new_order]])  

          3         2         1         4      mean         0
0  0.575223  0.719802  0.361846  0.449205  0.500678  0.397312
1  0.584221  0.992154  0.522337  0.042739  0.485741  0.287256
2  0.167698  0.149296  0.464172  0.793634  0.491923  0.884812
3  0.862769  0.046006  0.500179  0.651065  0.543382  0.656891
4  0.468954  0.438760  0.223489  0.308509  0.422683  0.673702
5  0.572475  0.100932  0.093050  0.416471  0.389390  0.764020
6  0.556980  0.626101  0.248186  0.559413  0.449972  0.259181
7  0.308755  0.096072  0.075461  0.157078  0.207592  0.400591
8  0.997547  0.340573  0.368987  0.011892  0.471749  0.639745
9  0.899230  0.168839  0.714160  0.359690  0.438500  0.050582

Et pour le cas spécifique de la question de OP:

new_order = [-1,0,1,2,3,4]
df = df[df.columns[new_order]]
print(df)

       mean         0         1         2         3         4
0  0.500678  0.397312  0.361846  0.719802  0.575223  0.449205
1  0.485741  0.287256  0.522337  0.992154  0.584221  0.042739
2  0.491923  0.884812  0.464172  0.149296  0.167698  0.793634
3  0.543382  0.656891  0.500179  0.046006  0.862769  0.651065
4  0.422683  0.673702  0.223489  0.438760  0.468954  0.308509
5  0.389390  0.764020  0.093050  0.100932  0.572475  0.416471
6  0.449972  0.259181  0.248186  0.626101  0.556980  0.559413
7  0.207592  0.400591  0.075461  0.096072  0.308755  0.157078
8  0.471749  0.639745  0.368987  0.340573  0.997547  0.011892
9  0.438500  0.050582  0.714160  0.168839  0.899230  0.359690

Le principal problème de cette approche est qu’appeler le même code plusieurs fois donnera des résultats différents à chaque fois. Il faut donc faire attention :)

35
Yuca

Vous devez créer une nouvelle liste de vos colonnes dans l'ordre souhaité, puis utiliser df = df[cols] pour réorganiser les colonnes dans ce nouvel ordre.

cols = ['mean']  + [col for col in df if col != 'mean']
df = df[cols]

Vous pouvez également utiliser une approche plus générale. Dans cet exemple, la dernière colonne (indiquée par -1) est insérée en tant que première colonne.

cols = [df.columns[-1]] + [col for col in df if col != df.columns[-1]]
df = df[cols]

Vous pouvez également utiliser cette approche pour réorganiser les colonnes dans l'ordre souhaité si elles sont présentes dans le DataFrame.

inserted_cols = ['a', 'b', 'c']
cols = ([col for col in inserted_cols if col in df] 
        + [col for col in df if col not in inserted cols])
df = df[cols]
27
Alexander

J'ai moi-même rencontré une question similaire et je voulais simplement ajouter ce sur quoi je me suis mis d'accord. J'ai aimé la reindex_axis() method pour changer l'ordre des colonnes. Cela a fonctionné:

df = df.reindex_axis(['mean'] + list(df.columns[:-1]), axis=1)

Une autre méthode basée sur le commentaire de @Jorge:

df = df.reindex(columns=['mean'] + list(df.columns[:-1]))

Bien que reindex_axis semble être légèrement plus rapide dans les micro-repères que reindex, je pense que je préfère ce dernier pour sa franchise.

16
clocker

Faites simplement,

df = df[['mean'] + df.columns[:-1].tolist()]
15
Napitupulu Jon

Cette fonction vous évite de lister toutes les variables de votre jeu de données pour en commander quelques-unes.

def order(frame,var):
    if type(var) is str:
        var = [var] #let the command take a string or list
    varlist =[w for w in frame.columns if w not in var]
    frame = frame[var+varlist]
    return frame 

Il faut deux arguments, le premier est l'ensemble de données, le second sont les colonnes de l'ensemble de données que vous souhaitez mettre au premier plan.

Donc, dans mon cas, j'ai un ensemble de données appelé Frame avec les variables A1, A2, B1, B2, Total et Date. Si je veux amener Total au premier plan, tout ce que je dois faire est:

frame = order(frame,['Total'])

Si je veux mettre Total et Date au premier plan, alors je fais:

frame = order(frame,['Total','Date'])

MODIFIER:

Un autre moyen utile de l'utiliser est que si vous avez une table inconnue et que vous recherchez des variables contenant un terme particulier, comme VAR1, VAR2, ... vous pouvez exécuter quelque chose comme:

frame = order(frame,[v for v in frame.columns if "VAR" in v])
14
seeiespi

Vous pouvez faire ce qui suit (emprunter des parties de la réponse d’Aman):

cols = df.columns.tolist()
cols.insert(0, cols.pop(-1))

cols
>>>['mean', 0L, 1L, 2L, 3L, 4L]

df = df[cols]
11
otteheng

Tapez simplement le nom de la colonne que vous souhaitez modifier et définissez l'index pour le nouvel emplacement.

def change_column_order(df, col_name, index):
    cols = df.columns.tolist()
    cols.remove(col_name)
    cols.insert(index, col_name)
    return df[cols]

Pour votre cas, cela ressemblerait à:

df = change_column_order(df, 'mean', 0)
8
ccerhan

Déplacer n'importe quelle colonne à n'importe quelle position:

import pandas as pd
df = pd.DataFrame({"A": [1,2,3], 
                   "B": [2,4,8], 
                   "C": [5,5,5]})

cols = df.columns.tolist()
column_to_move = "C"
new_position = 1

cols.insert(new_position, cols.pop(cols.index(column_to_move)))
df = df[cols]
7
pomber

Le moyen le plus simple serait de changer l'ordre des noms de colonnes comme ceci

df = df[['mean', Col1,Col2,Col3]]

7
Gayatri

Cette question a reçu une réponse: avant mais reindex_axis est obsolète maintenant, donc je suggérerais d'utiliser:

df.reindex(sorted(df.columns), axis=1)
5
dmvianna

set():

Une approche simple consiste à utiliser set(), en particulier lorsque vous avez une longue liste de colonnes et que vous ne souhaitez pas les gérer manuellement:

cols = list(set(df.columns.tolist()) - set(['mean']))
cols.insert(0, 'mean')
df = df[cols]
4
Shoresh

Voici un moyen de déplacer une colonne existante qui modifiera le bloc de données existant.

my_column = df.pop('column name')
df.insert(3, my_column.name, my_column)
4
Joe Heffer

Que diriez-vous d'utiliser "T"?

df.T.reindex(['mean',0,1,2,3,4]).T
3
ZEE

J'ai essayé la fonction insert() comme suggéré par Wes McKinney.

df.insert (0, 'moyen', df.mean (1))

Cela a donné le résultat souhaité par Timmie, sur une ligne, sans avoir à déplacer la dernière colonne.

3
Gan William

@clocker: Votre solution m'a été très utile, car je souhaitais placer deux colonnes devant une base de données où je ne connaissais pas exactement le nom de toutes les colonnes, car elles étaient générées à partir d'une instruction pivot auparavant. Donc, si vous êtes dans la même situation: pour mettre devant vous des colonnes dont vous connaissez le nom et les laisser suivre par "toutes les autres colonnes", j'ai proposé la solution générale suivante;

df = df.reindex_axis(['Col1','Col2'] + list(df.columns.drop(['Col1','Col2'])), axis=1)
2
matthhias

Vous pouvez utiliser reindex qui peut être utilisé pour les deux axes:

df
#           0         1         2         3         4      mean
# 0  0.943825  0.202490  0.071908  0.452985  0.678397  0.469921
# 1  0.745569  0.103029  0.268984  0.663710  0.037813  0.363821
# 2  0.693016  0.621525  0.031589  0.956703  0.118434  0.484254
# 3  0.284922  0.527293  0.791596  0.243768  0.629102  0.495336
# 4  0.354870  0.113014  0.326395  0.656415  0.172445  0.324628
# 5  0.815584  0.532382  0.195437  0.829670  0.019001  0.478415
# 6  0.944587  0.068690  0.811771  0.006846  0.698785  0.506136
# 7  0.595077  0.437571  0.023520  0.772187  0.862554  0.538182
# 8  0.700771  0.413958  0.097996  0.355228  0.656919  0.444974
# 9  0.263138  0.906283  0.121386  0.624336  0.859904  0.555009

df.reindex(['mean', *range(5)], axis=1)

#        mean         0         1         2         3         4
# 0  0.469921  0.943825  0.202490  0.071908  0.452985  0.678397
# 1  0.363821  0.745569  0.103029  0.268984  0.663710  0.037813
# 2  0.484254  0.693016  0.621525  0.031589  0.956703  0.118434
# 3  0.495336  0.284922  0.527293  0.791596  0.243768  0.629102
# 4  0.324628  0.354870  0.113014  0.326395  0.656415  0.172445
# 5  0.478415  0.815584  0.532382  0.195437  0.829670  0.019001
# 6  0.506136  0.944587  0.068690  0.811771  0.006846  0.698785
# 7  0.538182  0.595077  0.437571  0.023520  0.772187  0.862554
# 8  0.444974  0.700771  0.413958  0.097996  0.355228  0.656919
# 9  0.555009  0.263138  0.906283  0.121386  0.624336  0.859904
2
silgon

Voici une fonction permettant de faire cela pour n’importe quel nombre de colonnes.

def mean_first(df):
    ncols = df.shape[1]        # Get the number of columns
    index = list(range(ncols)) # Create an index to reorder the columns
    index.insert(0,ncols)      # This puts the last column at the front
    return(df.assign(mean=df.mean(1)).iloc[:,index]) # new df with last column (mean) first
2
freeB

DataFrame.sort_index(axis=1) est assez propre . Vérifiez le document ici . Et puis concat

1
Shihe Zhang

Méthode la plus difficile dans le livre

df.insert(0,"test",df["mean"])
df=df.drop(columns=["mean"]).rename(columns={"test":"mean"})
1
Kaustubh J

Je crois que @ réponse d'Aman est le meilleur si vous connaissez l'emplacement de l'autre colonne.

Si vous ne connaissez pas l'emplacement de mean, mais avez seulement son nom, vous ne pouvez pas recourir directement à cols = cols[-1:] + cols[:-1]. Voici la meilleure chose que je pourrais faire:

meanDf = pd.DataFrame(df.pop('mean'))
# now df doesn't contain "mean" anymore. Order of join will move it to left or right:
meanDf.join(df) # has mean as first column
df.join(meanDf) # has mean as last column
1
FooBar

J'ai bien aimé réponse de Shoresh utiliser la fonctionnalité set pour supprimer les colonnes lorsque vous ne connaissez pas l'emplacement. Cependant, cela ne fonctionne pas pour moi, car je dois conserver l'ordre des colonnes d'origine (qui contient des colonnes arbitraires). Étiquettes).

J'ai obtenu que cela fonctionne bien en utilisant IndexedSet à partir du paquetage boltons.

J'avais aussi besoin de rajouter plusieurs étiquettes de colonnes, alors pour un cas plus général, j'ai utilisé le code suivant:

from boltons.setutils import IndexedSet
cols = list(IndexedSet(df.columns.tolist()) - set(['mean', 'std']))
cols[0:0] =['mean', 'std']
df = df[cols]

J'espère que cela sera utile à tous ceux qui recherchent une solution générale sur ce sujet.

1
Jamelade