Comment changer l'ordre des colonnes DataFrame?

880

J'ai les éléments suivants DataFrame( df):

import numpy as np
import pandas as pd

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

J'ajoute plus de colonnes par affectation:

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

Comment puis-je déplacer la colonne meanvers l'avant, c'est-à-dire la définir comme première colonne sans modifier l'ordre des autres colonnes?

Timmie
la source
1
Pour une solution généralisée basée sur NumPy, voir Comment déplacer une colonne dans une trame de données pandas , suppose un seul niveau de colonne, c'est-à-dire non MultiIndex.
jpp
Après avoir suffisamment cherché, j'ai obtenu ce meilleur lien pour les colonnes réorganisant plusieurs logiques en termes assez simples [logique de réorganisation des colonnes pour les pandas] [ datasciencemadesimple.com/…
ravibeli

Réponses:

853

Un moyen simple serait de réaffecter la trame de données avec une liste des colonnes, réorganisées au besoin.

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 colscomme vous le souhaitez. Voici comment j'ai déplacé le dernier élément vers la première position:

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

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

Réorganisez ensuite la trame de données 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
Un homme
la source
17
dans le cas où vous obtenez "ne peut pas concaténer les objets 'str' et 'list'", assurez-vous que [] la valeur str dans cols: cols = [cols [7]] + cols [: 7] + cols [8:]
moeabdol
3
@FooBar Ce n'est pas une union définie, c'est une concaténation de deux listes ordonnées.
Aman
3
@Aman Je souligne simplement que votre code est obsolète. La gestion de votre message est à votre discrétion.
FooBar
2
@FooBar, le type de colsest list; il autorise même les doublons (qui seront supprimés lorsqu'ils seront utilisés sur la trame de données). Vous pensez aux Indexobjets.
alexis
8
Cela implique de copier TOUTES les données, ce qui est très inefficace. Je souhaitais que les pandas aient un moyen de le faire sans créer de copie.
Konstantin
442

Vous pouvez également faire quelque chose comme ceci:

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 déposer dans la première fonction

freddygv
la source
8
Vous pouvez également obtenir la liste des colonnes avec list (df.columns)
Jim
8
oudf.columns.tolist()
Jim
Pour les débutants comme moi, réorganisez la liste que vous obtenez des cols. Ensuite, df = df [cols], c'est-à-dire que la liste réorganisée est déposée dans la première expression sans un seul ensemble de crochets.
Sid
Les noms des colonnes seront des nombres entiers en 3.x df = df[['mean1', 0, 1, 2, 3]]
prosti
1
Je ne pense pas que ce soit une bonne réponse car elle ne fournit pas de code sur la façon de changer l'ordre des colonnes de n'importe quel cadre de données. Supposons que j'importe un fichier csv en tant que pandas pd as pd.read_csv(). Comment votre réponse peut-elle être utilisée pour modifier l'ordre des colonnes?
Robvh
312

Attribuez simplement les noms de colonne dans l'ordre que vous souhaitez:

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 «moyenne» 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
fixxxer
la source
7
Fait-il une copie?
user3226167
21
@NicholasMorley - Ce n'est pas la meilleure réponse si vous avez, disons, 1000 colonnes dans votre df.
AGS
1
il ne semble pas que vous vous assigniez à ce <df>.columnsque vous prétendez au départ
fan numéro un de Bjorks le
8
C'est la meilleure réponse pour un petit nombre de colonnes.
Dongkyu Choi
2
Ceci n'est qu'une copie de la réponse précédente de @freddygv. Celui-là devrait être la réponse acceptée, pas celle-ci.
James Hirschorn
134

Que diriez-vous:

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

http://pandas.pydata.org/pandas-docs/stable/dsintro.html#column-selection-addition-deletion

Wes McKinney
la source
35
Serait-ce une future fonctionnalité à ajouter pandas? quelque chose comme ça df.move(0,df.mean)?
Jason
Oh mec, ça fonctionne même comme ça df_metadata.insert(0,'Db_name',"raw_data")(Code non pertinent pour ce sujet)
Aetos
3
Beau. Et cela arrive aussi sur place.
cucu8
2
Il s'agit d'une solution évolutive, car d'autres solutions saisissent manuellement les noms des colonnes.
CKM
Cela fonctionne pour la question de l'OP, lors de la création d'une nouvelle colonne, mais pas pour le déplacement d'une colonne; tenter de déplacer les résultats dans*** ValueError: cannot insert mean, already exists
spinup
122

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']) ))
Alvaro Joao
la source
2
J'ai essayé de définir, copy=Falsemais il semble que reindex_axiscrée toujours une copie.
Konstantin
1
@Konstantin pouvez-vous créer une autre question sur ce problème? Il serait préférable d'avoir plus de contexte
Alvaro Joao
57

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 comme 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 un 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]
Alexandre
la source
47
import numpy as np
import pandas as pd
df = pd.DataFrame()
column_names = ['x','y','z','mean']
for col in column_names: 
    df[col] = np.random.randint(0,100, size=10000)

Vous pouvez essayer les solutions suivantes:

Solution 1:

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

Solution 2:


df = df[['mean', 'x', 'y', 'z']]

Solution 3:

col = df.pop("mean")
df = df.insert(0, col.name, col)

Solution 4:

df.set_index(df.columns[-1], inplace=True)
df.reset_index(inplace=True)

Solution 5:

cols = list(df)
cols = [cols[-1]] + cols[:-1]
df = df[cols]

solution 6:

order = [1,2,3,0] # setting column's order
df = df[[df.columns[i] for i in order]]

Comparaison de temps:

Solution 1:

Temps processeur: utilisateur 1,05 ms, sys: 35 µs, total: 1,08 ms Temps de paroi: 995 µs

Solution 2 :

Temps CPU: utilisateur 933 µs, sys: 0 ns, total: 933 µs Temps de mur: 800 µs

Solution 3 :

Temps CPU: utilisateur 0 ns, sys: 1,35 ms, total: 1,35 ms Temps de mur: 1,08 ms

Solution 4 :

Temps processeur: utilisateur 1,23 ms, sys: 45 µs, total: 1,27 ms Temps de paroi: 986 µs

Solution 5 :

Temps processeur: utilisateur 1,09 ms, sys: 19 µs, total: 1,11 ms Temps de paroi: 949 µs

Solution 6 :

Temps CPU: utilisateur 955 µs, sys: 34 µs, total: 989 µs Temps de paroi: 859 µs

Pygirl
la source
1
Une si belle réponse, merci.
qasimalbaqali
1
la solution 1 est ce dont j'avais besoin car j'ai trop de colonnes (53), merci
ratnesh
@Pygirl dont la valeur indique le temps réel réel? (utilisateur, sys, temps total ou mural)
sergzemsk
1
C'est pour moi la meilleure réponse au problème. Autant de solutions (dont une dont j'avais besoin) et d'approche simple. Merci!
Gustavo Rottgering
1
Solution 6 (pas de compréhension de liste):df = df.iloc[:, [1, 2, 3, 0]]
Dmitriy Work
43

A partir d'août 2018:

Si les noms de vos colonnes sont trop longs pour être saisis, vous pouvez spécifier le nouvel ordre via 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 d'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 avec cette approche est que le fait d'appeler plusieurs fois le même code créera des résultats différents à chaque fois, il faut donc être prudent :)

Yuca
la source
17

Cette fonction vous évite d'avoir à lister toutes les variables de votre jeu de données juste 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 prend 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 en avant.

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, il me suffit de:

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

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

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

ÉDITER:

Une autre façon utile de l'utiliser est que, si vous avez une table inconnue et que vous recherchez des variables avec 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])
seeiespi
la source
17

Je suis tombé sur une question similaire moi-même et je voulais juste ajouter ce sur quoi je me suis installé. J'ai aimé le reindex_axis() methodpour 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_axissemble être légèrement plus rapide dans les micro-benchmarks que reindex, je pense que je préfère ce dernier pour sa franchise.

horloge
la source
6
C'était une bonne solution, mais reindex_axis sera obsolète. J'ai utilisé la réindexation, et cela a très bien fonctionné.
Jorge
15

Faites simplement,

df = df[['mean'] + df.columns[:-1].tolist()]
Napitupulu Jon
la source
TypeError: impossible de convertir un objet 'int' en str implicitement
parvij
pourrait être l'API a changé, vous pouvez également le faire ... order = df.columns.tolist() df['mean'] = df.mean(1) df.columns = ['mean'] + order
Napitupulu Jon
1
Une variation de cela a bien fonctionné pour moi. Avec une liste existante headers, qui a été utilisée pour créer un dict qui a ensuite été utilisé pour créer le DataFrame, j'ai appelé df.reindex(columns=headers). Le seul problème que j'ai rencontré était que j'avais déjà appelé df.set_index('some header name', inplace=True), donc lorsque la réindexation a été effectuée, il a ajouté une autre colonne nommée some header namecar la colonne d'origine était maintenant l'index. Quant à la syntaxe spécifiée ci-dessus, ['mean'] + df.columnsdans l'interpréteur python me donneIndex(u'meanAddress', u'meanCity', u'meanFirst Name'...
hlongmore
1
@hlongmore: Je ne sais pas quel est votre code précédent, mais l'édition devrait fonctionner (en utilisant 0.19.2)
Napitupulu Jon
L'édition fonctionne en effet (je suis sur 0.20.2). Dans mon cas, j'ai déjà les colonnes que je veux, donc je pense que df.reindex () est ce que je devrais vraiment utiliser.
hlongmore
11

Vous pouvez faire ce qui suit (en empruntant 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]
otteheng
la source
10

Saisissez simplement le nom de la colonne que vous souhaitez modifier et définissez l'index du 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)
ccerhan
la source
Ceci est sous
zelusp
8

Déplacement d'une colonne vers 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]
bombardier
la source
7

Je pense que c'est une solution légèrement plus soignée:

df.insert(0,'mean', df.pop("mean"))

Cette solution est quelque peu similaire à la solution de @JoeHeffer mais il s'agit d'un liner.

Ici, nous "mean"supprimons la colonne du cadre de données et l'attachons à l'index 0avec le même nom de colonne.

erncyp
la source
5

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

my_column = df.pop('column name')
df.insert(3, my_column.name, my_column)
Joe Heffer
la source
5

Cette question a été répondu avant mais reindex_axis est maintenant dépréciée donc je suggère d'utiliser:

df.reindex(sorted(df.columns), axis=1)
dmvianna
la source
19
Non, c'est différent. Là, l'utilisateur veut trier toutes les colonnes par nom. Ici, ils veulent déplacer une colonne vers la première colonne tout en laissant intact l'ordre des autres colonnes.
smci
1
Et si vous ne voulez pas qu'ils soient triés?
Chankey Pathak
cela renvoie une copie, ne fonctionne pas sur place
rotation le
3

Que diriez-vous d'utiliser "T"?

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

@clocker: Votre solution m'a été très utile, car je voulais mettre deux colonnes en avant à partir d'une trame de données où je ne connais pas exactement les noms de toutes les colonnes, car elles sont générées à partir d'une instruction pivot auparavant. Donc, si vous êtes dans la même situation: Pour mettre en avant des colonnes dont vous connaissez le nom, puis les laisser suivre par "toutes les autres colonnes", j'ai trouvé la solution générale suivante;

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

set():

Une approche simple utilise 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]
Shoresh
la source
2
Une mise en garde: l'ordre des colonnes disparaît si vous le mettez dans l'ensemble
pvarma
Intéressant! @ user1930402 J'ai essayé l'approche ci-dessus à plusieurs reprises et je n'ai jamais eu de problème. Je vais vérifier à nouveau.
Shoresh
2

J'ai aimé la réponse de Shoresh pour utiliser la fonctionnalité d'ensemble pour supprimer les colonnes lorsque vous ne connaissez pas l'emplacement, mais cela n'a pas fonctionné pour moi car j'ai besoin de conserver l'ordre des colonnes d'origine (qui a des étiquettes de colonnes arbitraires).

J'ai réussi à faire fonctionner cela en utilisant IndexedSet à partir du package boltons.

J'ai également dû rajouter plusieurs étiquettes de colonne, donc 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 à toute personne recherchant ce fil pour une solution générale.

Jamelade
la source
Je suis un peu surpris! J'utilise setà cette fin assez souvent et je n'ai jamais eu à faire de commande.
Shoresh
2

Vous pouvez utiliser reindexce 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
silgon
la source
2

Voici une fonction pour le faire 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
freeB
la source
2

Méthode la plus hackeuse du livre

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

Je pense que cette fonction est plus simple. Il vous suffit de spécifier un sous-ensemble de colonnes au début ou à la fin ou les deux:

def reorder_df_columns(df, start=None, end=None):
    """
        This function reorder columns of a DataFrame.
        It takes columns given in the list `start` and move them to the left.
        Its also takes columns in `end` and move them to the right.
    """
    if start is None:
        start = []
    if end is None:
        end = []
    assert isinstance(start, list) and isinstance(end, list)
    cols = list(df.columns)
    for c in start:
        if c not in cols:
            start.remove(c)
    for c in end:
        if c not in cols or c in start:
            end.remove(c)
    for c in start + end:
        cols.remove(c)
    cols = start + cols + end
    return df[cols]
hayj
la source
1

Je pense que la réponse de @ Aman est la meilleure si vous connaissez l'emplacement de l'autre colonne.

Si vous ne connaissez pas l'emplacement de mean, mais que vous ne connaissez que son nom, vous ne pouvez pas y recourir directement cols = cols[-1:] + cols[:-1]. Voici la prochaine meilleure chose que j'ai pu trouver:

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
FooBar
la source
1

Le simple retournement aide souvent.

df[df.columns[::-1]]

Ou mélangez simplement pour un look.

import random
cols = list(df.columns)
random.shuffle(cols)
df[cols]
plhn
la source
0

La plupart des réponses n'ont pas généralisé suffisamment et la méthode pandas reindex_axis est un peu fastidieuse, donc j'offre une fonction simple pour déplacer un nombre arbitraire de colonnes vers n'importe quelle position en utilisant un dictionnaire où clé = nom de colonne et valeur = position vers laquelle se déplacer. Si votre trame de données est grande, passez True à 'big_data' alors la fonction renverra la liste des colonnes ordonnées. Et vous pouvez utiliser cette liste pour découper vos données.

def order_column(df, columns, big_data = False):

    """Re-Orders dataFrame column(s)
       Parameters : 
       df      -- dataframe
       columns -- a dictionary:
                  key   = current column position/index or column name
                  value = position to move it to  
       big_data -- boolean 
                  True = returns only the ordered columns as a list
                          the user user can then slice the data using this
                          ordered column
                  False = default - return a copy of the dataframe
    """
    ordered_col = df.columns.tolist()

    for key, value in columns.items():

        ordered_col.remove(key)
        ordered_col.insert(value, key)

    if big_data:

        return ordered_col

    return df[ordered_col]

# e.g.
df = pd.DataFrame({'chicken wings': np.random.rand(10, 1).flatten(), 'taco': np.random.rand(10,1).flatten(),
                          'coffee': np.random.rand(10, 1).flatten()})
df['mean'] = df.mean(1)

df = order_column(df, {'mean': 0, 'coffee':1 })

>>>

production

col = order_column(df, {'mean': 0, 'coffee':1 }, True)

col
>>>
['mean', 'coffee', 'chicken wings', 'taco']

# you could grab it by doing this

df = df[col]
escha
la source
0

J'ai un cas d'utilisation très spécifique pour réorganiser les noms de colonnes dans les pandas. Parfois, je crée une nouvelle colonne dans une trame de données basée sur une colonne existante. Par défaut, les pandas insèrent ma nouvelle colonne à la fin, mais je veux que la nouvelle colonne soit insérée à côté de la colonne existante dont elle est dérivée.

entrez la description de l'image ici

def rearrange_list(input_list, input_item_to_move, input_item_insert_here):
    '''
    Helper function to re-arrange the order of items in a list.
    Useful for moving column in pandas dataframe.

    Inputs:
        input_list - list
        input_item_to_move - item in list to move
        input_item_insert_here - item in list, insert before 

    returns:
        output_list
    '''
    # make copy for output, make sure it's a list
    output_list = list(input_list)

    # index of item to move
    idx_move = output_list.index(input_item_to_move)

    # pop off the item to move
    itm_move = output_list.pop(idx_move)

    # index of item to insert here
    idx_insert = output_list.index(input_item_insert_here)

    # insert item to move into here
    output_list.insert(idx_insert, itm_move)

    return output_list


import pandas as pd

# step 1: create sample dataframe
df = pd.DataFrame({
    'motorcycle': ['motorcycle1', 'motorcycle2', 'motorcycle3'],
    'initial_odometer': [101, 500, 322],
    'final_odometer': [201, 515, 463],
    'other_col_1': ['blah', 'blah', 'blah'],
    'other_col_2': ['blah', 'blah', 'blah']
})
print('Step 1: create sample dataframe')
display(df)
print()

# step 2: add new column that is difference between final and initial
df['change_odometer'] = df['final_odometer']-df['initial_odometer']
print('Step 2: add new column')
display(df)
print()

# step 3: rearrange columns
ls_cols = df.columns
ls_cols = rearrange_list(ls_cols, 'change_odometer', 'final_odometer')
df=df[ls_cols]
print('Step 3: rearrange columns')
display(df)
pk2019
la source
0

Une solution assez simple qui a fonctionné pour moi est d'utiliser .reindex sur df.columns:

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