Move column by name to front of table in pandas

Question:

Here is my df:

                             Net   Upper   Lower  Mid  Zsore
Answer option                                                
More than once a day          0%   0.22%  -0.12%   2    65 
Once a day                    0%   0.32%  -0.19%   3    45
Several times a week          2%   2.45%   1.10%   4    78
Once a week                   1%   1.63%  -0.40%   6    65

How can I move a column by name ("Mid") to the front of the table, index 0. This is what the result should look like:

                             Mid   Upper   Lower  Net  Zsore
Answer option                                                
More than once a day          2   0.22%  -0.12%   0%    65 
Once a day                    3   0.32%  -0.19%   0%    45
Several times a week          4   2.45%   1.10%   2%    78
Once a week                   6   1.63%  -0.40%   1%    65

My current code moves the column by index using df.columns.tolist() but I’d like to shift it by name.

Asked By: Boosted_d16

||

Answers:

We can use loc to reorder by passing a list:

In [27]:
# get a list of columns
cols = list(df)
# move the column to head of list using index, pop and insert
cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[27]:
['Mid', 'Net', 'Upper', 'Lower', 'Zsore']
In [28]:
# use ix to reorder
df = df.loc[:, cols]
df
Out[28]:
                      Mid Net  Upper   Lower  Zsore
Answer_option                                      
More_than_once_a_day    2  0%  0.22%  -0.12%     65
Once_a_day              3  0%  0.32%  -0.19%     45
Several_times_a_week    4  2%  2.45%   1.10%     78
Once_a_week             6  1%  1.63%  -0.40%     65

Another method is to take a reference to the column and reinsert it at the front:

In [39]:
mid = df['Mid']
df.drop(labels=['Mid'], axis=1,inplace = True)
df.insert(0, 'Mid', mid)
df
Out[39]:
                      Mid Net  Upper   Lower  Zsore
Answer_option                                      
More_than_once_a_day    2  0%  0.22%  -0.12%     65
Once_a_day              3  0%  0.32%  -0.19%     45
Several_times_a_week    4  2%  2.45%   1.10%     78
Once_a_week             6  1%  1.63%  -0.40%     65

You can, with very early versions of Pandas, also use ix to achieve the same results:

df = df.ix[:, cols]

But ix was deprecated from pandas 0.20.0 onwards and was discontinued as of Pandas 1.0.

Answered By: EdChum

You can use the df.reindex() function in pandas.
df is

                      Net  Upper   Lower  Mid  Zsore
Answer option                                      
More than once a day  0%  0.22%  -0.12%    2     65
Once a day            0%  0.32%  -0.19%    3     45
Several times a week  2%  2.45%   1.10%    4     78
Once a week           1%  1.63%  -0.40%    6     65

define an list of column names

cols = df.columns.tolist()
cols
Out[13]: ['Net', 'Upper', 'Lower', 'Mid', 'Zsore']

move the column name to wherever you want

cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[16]: ['Mid', 'Net', 'Upper', 'Lower', 'Zsore']

then use df.reindex() function to reorder

df = df.reindex(columns= cols)

out put is: df

                      Mid  Upper   Lower Net  Zsore
Answer option                                      
More than once a day    2  0.22%  -0.12%  0%     65
Once a day              3  0.32%  -0.19%  0%     45
Several times a week    4  2.45%   1.10%  2%     78
Once a week             6  1.63%  -0.40%  1%     65
Answered By: Sachinmm

I didn’t like how I had to explicitly specify all the other column in the other solutions.

cfg_col_sel = ['Mid', 'Zscore']
cfg_col_sel = cfg_col_sel+[s for s in df.columns if not s in cfg_col_sel]
df = df[cfg_col_sel]

This is another way of doing it but less flexible

df = df.set_index('Mid').reset_index()

Answered By: citynorman

Here is a generic set of code that I frequently use to rearrange the position of columns. You may find it useful.

cols = df.columns.tolist()
n = int(cols.index('Mid'))
cols = [cols[n]] + cols[:n] + cols[n+1:]
df = df[cols]
Answered By: Bhagabat Behera

Maybe I’m missing something, but a lot of these answers seem overly complicated. You should be able to just set the columns within a single list:

Column to the front:

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

Or if instead, you want to move it to the back:

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

Or if you wanted to move more than one column:

cols_to_move = ['Mid', 'Zsore']
df           = df[ cols_to_move + [ col for col in df.columns if col not in cols_to_move ] ]
Answered By: elPastor

To reorder the rows of a DataFrame just use a list as follows.

df = df[['Mid', 'Net', 'Upper', 'Lower', 'Zsore']]

This makes it very obvious what was done when reading the code later. Also use:

df.columns
Out[1]: Index(['Net', 'Upper', 'Lower', 'Mid', 'Zsore'], dtype='object')

Then cut and paste to reorder.


For a DataFrame with many columns, store the list of columns in a variable and pop the desired column to the front of the list. Here is an example:

cols = [str(col_name) for col_name in range(1001)]
data = np.random.rand(10,1001)
df = pd.DataFrame(data=data, columns=cols)

mv_col = cols.pop(cols.index('77'))
df = df[[mv_col] + cols]

Now df.columns has.

Index(['77', '0', '1', '2', '3', '4', '5', '6', '7', '8',
       ...
       '991', '992', '993', '994', '995', '996', '997', '998', '999', '1000'],
      dtype='object', length=1001)
Answered By: Dustin Helliwell

I prefer this solution:

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

It’s simpler to read and faster than other suggested answers.

def move_column_inplace(df, col, pos):
    col = df.pop(col)
    df.insert(pos, col.name, col)

Performance assessment:

For this test, the currently last column is moved to the front in each repetition. In-place methods generally perform better. While citynorman’s solution can be made in-place, Ed Chum’s method based on .loc and sachinnm’s method based on reindex cannot.

While other methods are generic, citynorman’s solution is limited to pos=0. I didn’t observe any performance difference between df.loc[cols] and df[cols], which is why I didn’t include some other suggestions.

Original system (2019): Python 3.6.8 and pandas 0.24.2 on a MacBook Pro (Mid 2015).
Current system (2022): Python 3.10.5 and pandas 1.4.3 on a MacBook Pro (2021, Apple M1).

import numpy as np
import pandas as pd

n_cols = 11
df = pd.DataFrame(np.random.randn(200000, n_cols),
                  columns=range(n_cols))

def move_column_inplace(df, col, pos):
    col = df.pop(col)
    df.insert(pos, col.name, col)

def move_to_front_normanius_inplace(df, col):
    move_column_inplace(df, col, 0)
    return df

def move_to_front_chum(df, col):
    cols = list(df)
    cols.insert(0, cols.pop(cols.index(col)))
    return df.loc[:, cols]

def move_to_front_chum_inplace(df, col):
    col = df[col]
    df.drop(col.name, axis=1, inplace=True)
    df.insert(0, col.name, col)
    return df

def move_to_front_elpastor(df, col):
    cols = [col] + [ c for c in df.columns if c!=col ]
    return df[cols] # or df.loc[cols]

def move_to_front_sachinmm(df, col):
    cols = df.columns.tolist()
    cols.insert(0, cols.pop(cols.index(col)))
    df = df.reindex(columns=cols, copy=False)
    return df

def move_to_front_citynorman_inplace(df, col):
    # This approach exploits that reset_index() moves the index
    # at the first position of the data frame.
    df.set_index(col, inplace=True)
    df.reset_index(inplace=True)
    return df

def test(method, df):
    col = np.random.randint(0, n_cols)
    method(df, col)

col = np.random.randint(0, n_cols)
ret_mine = move_to_front_normanius_inplace(df.copy(), col)
ret_chum1 = move_to_front_chum(df.copy(), col)
ret_chum2 = move_to_front_chum_inplace(df.copy(), col)
ret_elpas = move_to_front_elpastor(df.copy(), col)
ret_sach = move_to_front_sachinmm(df.copy(), col)
ret_city = move_to_front_citynorman_inplace(df.copy(), col)

# Assert equivalence of solutions.
assert(ret_mine.equals(ret_chum1))
assert(ret_mine.equals(ret_chum2))
assert(ret_mine.equals(ret_elpas))
assert(ret_mine.equals(ret_sach))
assert(ret_mine.equals(ret_city))

Results:

# For n_cols = 11:
%timeit test(move_to_front_normanius_inplace, df)
# 137 µs ± 692 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 177 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 821 µs ± 11.8 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_chum, df)
# 926 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_elpastor, df)
# 901 µs ± 6.44 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 3.25 ms ± 32.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


# For n_cols = 31:
%timeit test(move_to_front_normanius_inplace, df)
# 188 µs ± 3.46 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 214 µs ± 649 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 5.17 ms ± 68.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum, df)
# 5.52 ms ± 82.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_elpastor, df)
# 5.48 ms ± 198 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 14.7 ms ± 317 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Above are the updated values for a rerun in 2022. The rankings have remained stable over the past years for different systems, although the absolute numbers have decreased by factors between 2 and 10, from which citynorman’s solution and my solution (normanius) have benefited the most.

Answered By: normanius

Here is a very simple answer to this.

Don’t forget the two (()) ‘brackets’ around columns names.Otherwise, it’ll give you an error.


# here you can add below line and it should work 
df = df[list(('Mid','Upper', 'Lower', 'Net','Zsore'))]
df

                             Mid   Upper   Lower  Net  Zsore
Answer option                                                
More than once a day          2   0.22%  -0.12%   0%    65 
Once a day                    3   0.32%  -0.19%   0%    45
Several times a week          4   2.45%   1.10%   2%    78
Once a week                   6   1.63%  -0.40%   1%    65
Answered By: rra

The most simplist thing you can try is:

df=df[[ 'Mid',   'Upper',   'Lower', 'Net'  , 'Zsore']]
df.set_index('Mid').reset_index()

seems to be a pretty easy way about this.

Answered By: baxx

If you want to move to another place and reassign the name as well, you can do as the following:

df.insert(0, 'new col name', col)
df.pop("Mid")

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.insert.html

Answered By: Raphael G

If you want to move a column to the front of the dataframe, you can use
use set_index().

df.set_index(df.pop('column_name'), inplace=True)
df.reset_index(inplace=True)

You first need to set the column you want to bring to the front as the index of the dataframe (and we do a pop in order to drop the column from the original dataframe before setting it as the index in order to avoid name collision in the next action) and finally call reset_index() to make the old index the first column of the dataframe.


For more details see How to change the order of dataframe columns in pandas.

Answered By: Giorgos Myrianthous

You can use movecolumn package in Python to move columns:

pip install movecolumn

Then you can write your code as:

import movecolumn as mc
mc.MoveTo1(df,'mid')

Hope that helps.

P.S : The package can be found here. https://pypi.org/project/movecolumn/

Answered By: Saad Bin Munir

Easy and quick solution::

For pandas >= 1.3 (Edited in 2022):

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

How about (for Pandas < 1.3, the original answer)

df.insert(0, 'mean', df['mean'])
Answered By: Sachin

You can use these methods.

Here you will "delete" the Mid column. If you use the method pop() will delete the column from the db but it will keep it in memory. That’s why I put a variable equal to the column that we are goind to "delete".

column_mid = df.pop("Mid")

After that, you can use the method insert() which will allow you to put the column Mid in whichever position that you indicate. In this case will be the position 0.

df.insert(0, "Mid", column_mid)

And that’s it. If you have any query, let me know.

Regards!

Octavio Velázquez

Answered By: Octavio Velázquez
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.