¿Cómo cambiar el orden de las columnas de DataFrame?

Tengo el siguiente DataFrame ( df ):

 import numpy as np import pandas as pd df = pd.DataFrame(np.random.rand(10, 5)) 

Agrego más columnas por asignación:

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

¿Cómo puedo mover la mean la columna al frente, es decir, establecerla como primera columna sin tocar el orden de las otras columnas?

Una forma fácil sería reasignar el dataframe con una lista de las columnas, reorganizadas según sea necesario.

Esto es lo que tienes ahora:

 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'] 

Reorganiza los cols de la forma que quieras. Así es como moví el último elemento a la primera posición:

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

Luego reordena el dataframe de esta manera:

 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 

También podrías hacer algo como esto:

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

Puede obtener la lista de columnas con:

 cols = list(df.columns.values) 

La salida producirá:

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

… que luego es fácil de reorganizar manualmente antes de colocarlo en la primera función

Simplemente asigne los nombres de las columnas en el orden que desee:

 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]] 

Ahora, la columna ‘media’ sale en el frente:

 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 

En tu caso,

 df = df.reindex_axis(['mean',0,1,2,3,4], axis=1) 

Hará exactamente lo que quieras.

En mi caso (forma general):

 df = df.reindex_axis(sorted(df.columns), axis=1) df = df.reindex_axis(['opened'] + list([a for a in df.columns if a != 'opened']), axis=1) 

actualización enero 2018

Si quieres usar reindex :

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

Necesita crear una nueva lista de sus columnas en el orden deseado, luego use df = df[cols] para reorganizar las columnas en este nuevo orden.

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

También puede utilizar un enfoque más general. En este ejemplo, la última columna (indicada por -1) se inserta como la primera columna.

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

También puede usar este enfoque para reordenar columnas en un orden deseado si están presentes en el Marco de datos.

 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] 

Desde agosto de 2018:

Si los nombres de sus columnas son demasiado largos para escribir, puede especificar el nuevo orden a través de una lista de enteros con las posiciones:

Datos:

  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 

Ejemplo genérico:

 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 

Y para el caso específico de la pregunta 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 

El principal problema con este enfoque es que llamar al mismo código varias veces creará resultados diferentes cada vez, por lo que hay que tener cuidado 🙂

Simplemente hacer

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

Esta función evita tener que enumerar cada variable en su conjunto de datos solo para ordenar algunas de ellas.

 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 

Toma dos argumentos, el primero es el conjunto de datos, el segundo son las columnas en el conjunto de datos que desea traer al frente.

Así que en mi caso tengo un conjunto de datos llamado Frame con las variables A1, A2, B1, B2, Total y Fecha. Si quiero llevar a Total al frente, todo lo que tengo que hacer es:

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

Si quiero llevar el Total y la Fecha al frente, entonces hago:

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

EDITAR:

Otra forma útil de usar esto es que, si tiene una tabla desconocida y busca variables con un término en particular, como VAR1, VAR2, … puede ejecutar algo como:

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

Me encontré con una pregunta similar, y solo quería agregar lo que decidí. Me gustó el reindex_axis() method para cambiar el orden de las columnas. Esto funcionó:

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

Un método alternativo basado en el comentario de @Jorge:

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

Aunque reindex_axis parece ser un poco más rápido en los micro benchmarks que en reindex , creo que prefiero este último por su franqueza.

Puedes hacer lo siguiente (tomar partes prestadas de la respuesta de Aman):

 cols = df.columns.tolist() cols.insert(0, cols.pop(-1)) cols >>>['mean', 0L, 1L, 2L, 3L, 4L] df = df[cols] 

Simplemente escriba el nombre de la columna que desea cambiar y establezca el índice para la nueva ubicación.

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

Para tu caso, esto sería como:

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

Mover cualquier columna a cualquier posición:

 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] 

La forma más sencilla sería cambiar el orden de los nombres de columna de esta manera

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

Esta pregunta ha sido respondida anteriormente, pero reindex_axis está obsoleto ahora, así que sugiero usar:

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

set() :

Un enfoque simple es usar set() , en particular cuando tiene una larga lista de columnas y no quiere manejarlas manualmente:

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

¿Qué hay de usar “T”?

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

Probé la función insert() como lo sugirió Wes McKinney.

df.insert (0, ‘mean’, df.mean (1))

Esto obtuvo el resultado que Timmie quería, en una línea, sin la necesidad de mover esa última columna.

Aquí hay una forma de mover una columna existente que modificará el dataframe existente en su lugar.

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

@clocker: Su solución fue muy útil para mí, ya que quería traer dos columnas al frente desde un dataframe en el que no sé exactamente los nombres de todas las columnas, porque se generaron a partir de una statement dinámica antes. Entonces, si se encuentra en la misma situación: para traer las columnas al frente de las que sabe el nombre y luego dejar que sigan “todas las demás columnas”, se me ocurrió la siguiente solución general;

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

Puedes usar reindex que puede ser usado para ambos ejes:

 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 

Aquí hay una función para hacer esto para cualquier número de columnas.

 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 

Creo que la respuesta de @Aman es la mejor si conoces la ubicación de la otra columna.

Si no conoce la ubicación de la mean , pero solo tiene su nombre, no puede recurrir directamente a cols = cols[-1:] + cols[:-1] . Lo siguiente es lo mejor que podría encontrar:

 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 

DataFrame.sort_index(axis=1) está bastante limpio. Revise el documento aquí . Y luego concat

Me gustó la respuesta de Shoresh de usar la funcionalidad de configuración para eliminar columnas cuando no conoce la ubicación, sin embargo, esto no funcionó para mi propósito, ya que necesito mantener el orden de la columna original (que tiene tags de columna arbitrarias).

Sin embargo, conseguí que esto funcionara utilizando IndexedSet del paquete boltons.

También necesitaba volver a agregar tags de varias columnas, así que para un caso más general usé el siguiente código:

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

Espero que esto sea útil para cualquiera que busque en este hilo una solución general.

El método más extraño en el libro

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