384

Can I insert a column at a specific column index in pandas?

import pandas as pd
df = pd.DataFrame({'l':['a','b','c','d'], 'v':[1,2,1,2]})
df['n'] = 0

This will put column n as the last column of df, but isn't there a way to tell df to put n at the beginning?

HappyPy
  • 9,839
  • 13
  • 46
  • 68
  • [Insert a column at the beginning (leftmost end) of a DataFrame](https://stackoverflow.com/questions/46307681/insert-a-column-at-the-beginning-leftmost-end-of-a-dataframe/46307720#46307720) - more solutions + generalised solution for inserting any sequence (not just a constant value). – cs95 Feb 05 '19 at 22:03

6 Answers6

682

see docs: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.insert.html

using loc = 0 will insert at the beginning

df.insert(loc, column, value)

df = pd.DataFrame({'B': [1, 2, 3], 'C': [4, 5, 6]})

df
Out: 
   B  C
0  1  4
1  2  5
2  3  6

idx = 0
new_col = [7, 8, 9]  # can be a list, a Series, an array or a scalar   
df.insert(loc=idx, column='A', value=new_col)

df
Out: 
   A  B  C
0  7  1  4
1  8  2  5
2  9  3  6
cs95
  • 379,657
  • 97
  • 704
  • 746
Jeff
  • 125,376
  • 21
  • 220
  • 187
  • 33
    For future users, the new parameters are *"loc", "column",* and *"value"*. [Source](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.insert.html) – Peter Maguire Jan 24 '17 at 19:12
  • 1
    I counted and recounted the length of values and length of index after printing but keep getting `ValueError: Length of values does not match length of index ` – mLstudent33 Oct 17 '20 at 21:16
  • 10
    For future users, if you want to insert with the help of specific column name instead of index, use: `df.insert(df.columns.get_loc('col_name'), 'new_col_name', ser_to_insert)`. `insert` doesn't directly support column name use case but you can get the column index from column name and pass that. – Sulphur May 09 '21 at 23:58
  • Replace `value` with `pd.Series(value_list)` – DanielBell99 Apr 28 '22 at 14:45
72

If you want a single value for all rows:

df.insert(0,'name_of_column','')
df['name_of_column'] = value

Edit:

You can also:

df.insert(0,'name_of_column',value)
Hugo Vares
  • 977
  • 7
  • 7
18
df.insert(loc, column_name, value)

This will work if there is no other column with the same name. If a column, with your provided name already exists in the dataframe, it will raise a ValueError.

You can pass an optional parameter allow_duplicates with True value to create a new column with already existing column name.

Here is an example:



    >>> df = pd.DataFrame({'b': [1, 2], 'c': [3,4]})
    >>> df
       b  c
    0  1  3
    1  2  4
    >>> df.insert(0, 'a', -1)
    >>> df
       a  b  c
    0 -1  1  3
    1 -1  2  4
    >>> df.insert(0, 'a', -2)
    Traceback (most recent call last):
      File "", line 1, in 
      File "C:\Python39\lib\site-packages\pandas\core\frame.py", line 3760, in insert
        self._mgr.insert(loc, column, value, allow_duplicates=allow_duplicates)
      File "C:\Python39\lib\site-packages\pandas\core\internals\managers.py", line 1191, in insert
        raise ValueError(f"cannot insert {item}, already exists")
    ValueError: cannot insert a, already exists
    >>> df.insert(0, 'a', -2,  allow_duplicates = True)
    >>> df
       a  a  b  c
    0 -2 -1  1  3
    1 -2 -1  2  4

mhc
  • 289
  • 2
  • 8
  • This is brilliant, actually also suggested in Pandas [official documentation](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.insert.html). Thanks for bringing this up @mhc – nikhil int Mar 30 '22 at 14:22
17

You could try to extract columns as list, massage this as you want, and reindex your dataframe:

>>> cols = df.columns.tolist()
>>> cols = [cols[-1]]+cols[:-1] # or whatever change you need
>>> df.reindex(columns=cols)

   n  l  v
0  0  a  1
1  0  b  2
2  0  c  1
3  0  d  2

EDIT: this can be done in one line ; however, this looks a bit ugly. Maybe some cleaner proposal may come...

>>> df.reindex(columns=['n']+df.columns[:-1].tolist())

   n  l  v
0  0  a  1
1  0  b  2
2  0  c  1
3  0  d  2
cs95
  • 379,657
  • 97
  • 704
  • 746
Nic
  • 3,365
  • 3
  • 20
  • 31
4
A general 4-line routine

You can have the following 4-line routine whenever you want to create a new column and insert into a specific location loc.

df['new_column'] = ... #new column's definition
col = df.columns.tolist()
col.insert(loc, col.pop()) #loc is the column's index you want to insert into
df = df[col]

In your example, it is simple:

df['n'] = 0
col = df.columns.tolist()
col.insert(0, col.pop()) 
df = df[col]
Ka Wa Yip
  • 2,546
  • 3
  • 22
  • 35
3

Here is a very simple answer to this(only one line).

You can do that after you added the 'n' column into your df as follows.

import pandas as pd
df = pd.DataFrame({'l':['a','b','c','d'], 'v':[1,2,1,2]})
df['n'] = 0

df
    l   v   n
0   a   1   0
1   b   2   0
2   c   1   0
3   d   2   0

# here you can add the below code and it should work.
df = df[list('nlv')]
df

    n   l   v
0   0   a   1
1   0   b   2
2   0   c   1
3   0   d   2



However, if you have words in your columns names instead of letters. It should include two brackets around your column names. 

import pandas as pd
df = pd.DataFrame({'Upper':['a','b','c','d'], 'Lower':[1,2,1,2]})
df['Net'] = 0
df['Mid'] = 2
df['Zsore'] = 2

df

    Upper   Lower   Net Mid Zsore
0   a       1       0   2   2
1   b       2       0   2   2
2   c       1       0   2   2
3   d       2       0   2   2

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

   Mid  Upper   Lower   Net Zsore
0   2   a       1       0   2
1   2   b       2       0   2
2   2   c       1       0   2
3   2   d       2       0   2
rra
  • 809
  • 1
  • 8
  • 20
  • What if we wanted to add a few columns from another `df_other` to the `loc 0` and a few columns from `df_other` to the end of our df? – Amir Jan 27 '21 at 16:50