177

Is there a way to reorder columns in pandas dataframe based on my personal preference (i.e. not alphabetically or numerically sorted, but more like following certain conventions)?

Simple example:

frame = pd.DataFrame({
        'one thing':[1,2,3,4],
        'second thing':[0.1,0.2,1,2],
        'other thing':['a','e','i','o']})

produces this:

   one thing other thing  second thing
0          1           a           0.1
1          2           e           0.2
2          3           i           1.0
3          4           o           2.0

But instead, I would like this:

   one thing second thing  other thing
0          1           0.1           a
1          2           0.2           e
2          3           1.0           i
3          4           2.0           o

(Please, provide a generic solution rather than specific to this case. Many thanks.)

11 Answers 11

244

Just select the order yourself by typing in the column names. Note the double brackets:

frame = frame[['column I want first', 'column I want second'...etc.]]
Sign up to request clarification or add additional context in comments.

4 Comments

This only works with this rather small example. If you are reading data in from another source, like a csv file or a database table, you can't use this answer. And those seem to be much more common. The OP requested a general solution.
This is obviously a general solution. Even if you read column names and orders from a different csv file, you can extract column names to list and use above notation easily. What is the non-general point of this answer?
To do operations over the list of column names instead of typing them, remember that you can access them like this list(frame.columns), or similar.
I agree with alecelik and disagree with chrisfs - I used a column of the same dataframe, length 638, to reorder the columns, which had titles the same as the entries in that column. In a square dataframe, I applied the same permutation to rows and columns. df_MPs1 = df_MPs1[[pid for pid in df_MPs1['person_id']]]
163

You can use this:

column_names = ["onething", "secondthing", "otherthing"]

frame = frame.reindex(columns=column_names)

5 Comments

Even though most other solutions are more concise, I would consider this one to be the most readable for anybody who is not 100% familiar with pandas.
Remember to assign the return value to a variable though, this does not modify column order in-place (at least not in pandas v0.23`).
This works for me thanks?
Great suggestion, and most probably the easiest to understand if you are a newcomer to Pandas.
This is a really dangerous method: if you miss-spell a column name pandas will create a new column filled with NaN instead of raising an error!
92

UPDATE:

There is a useful package called pyjanitor. It improves pandas usability by providing many useful R-style API and is neatly integrated with pandas.

In particular, to reorder columns, you can simply do the following.

>>> import pandas as pd
>>> import janitor
>>> df = pd.DataFrame({"col1": [1, 1, 1], "col2": [2, 2, 2], "col3": [3, 3, 3]})
>>> df
   col1  col2  col3
0     1     2     3
1     1     2     3
2     1     2     3
>>> df.reorder_columns(['col3', 'col1'])
   col3  col1  col2
0     3     1     2
1     3     1     2
2     3     1     2


Here is a solution I use very often. When you have a large data set with tons of columns, you definitely do not want to manually rearrange all the columns.

What you can and, most likely, want to do is to just order the first a few columns that you frequently use, and let all other columns just be themselves. This is a common approach in R. df %>%select(one, two, three, everything())

So you can first manually type the columns that you want to order and to be positioned before all the other columns in a list cols_to_order.

Then you construct a list for new columns by combining the rest of the columns:

new_columns = cols_to_order + (frame.columns.drop(cols_to_order).tolist())

After this, you can use the new_columns as other solutions suggested.

import pandas as pd
frame = pd.DataFrame({
    'one thing': [1, 2, 3, 4],
    'other thing': ['a', 'e', 'i', 'o'],
    'more things': ['a', 'e', 'i', 'o'],
    'second thing': [0.1, 0.2, 1, 2],
})

cols_to_order = ['one thing', 'second thing']
new_columns = cols_to_order + (frame.columns.drop(cols_to_order).tolist())
frame = frame[new_columns]

   one thing  second thing other thing more things
0          1           0.1           a           a
1          2           0.2           e           e
2          3           1.0           i           i
3          4           2.0           o           o

2 Comments

brilliant, perfect. thank you for keeping me from having to type out every column name or index
How is that difficult to do this in pandas ffs? df %>% relocate(new_col) all day. ## ---- ## You could make that a function: def relocate(df, var): new_var_order = [var] + df.columns.drop(var).tolist() df = df[new_var_order] return(df)
33

You could also do something like df = df[['x', 'y', 'a', 'b']]

import pandas as pd
frame = pd.DataFrame({'one thing':[1,2,3,4],'second thing':[0.1,0.2,1,2],'other thing':['a','e','i','o']})
frame = frame[['second thing', 'other thing', 'one thing']]
print frame
   second thing other thing  one thing
0           0.1           a          1
1           0.2           e          2
2           1.0           i          3
3           2.0           o          4

Also, you can get the list of columns with:

cols = list(df.columns.values)

The output will produce something like this:

['x', 'y', 'a', 'b']

Which is then easy to rearrange manually.

Comments

13

Construct it with a list instead of a dictionary

frame = pd.DataFrame([
        [1, .1, 'a'],
        [2, .2, 'e'],
        [3,  1, 'i'],
        [4,  4, 'o']
    ], columns=['one thing', 'second thing', 'other thing'])

frame

   one thing  second thing other thing
0          1           0.1           a
1          2           0.2           e
2          3           1.0           i
3          4           4.0           o

1 Comment

I could not get 'column name': data to work inside a list as it does in a dict.
11

You can also use OrderedDict:

In [183]: from collections import OrderedDict

In [184]: data = OrderedDict()

In [185]: data['one thing'] = [1,2,3,4]

In [186]: data['second thing'] = [0.1,0.2,1,2]

In [187]: data['other thing'] = ['a','e','i','o']

In [188]: frame = pd.DataFrame(data)

In [189]: frame
Out[189]:
   one thing  second thing other thing
0          1           0.1           a
1          2           0.2           e
2          3           1.0           i
3          4           2.0           o

Comments

7

Add the 'columns' parameter:

frame = pd.DataFrame({
        'one thing':[1,2,3,4],
        'second thing':[0.1,0.2,1,2],
        'other thing':['a','e','i','o']},
        columns=['one thing', 'second thing', 'other thing']
)

Comments

7

Try indexing (so you want a generic solution not only for this, so index order can be just what you want):

l=[0,2,1] # index order
frame=frame[[frame.columns[i] for i in l]]

Now:

print(frame)

Is:

   one thing second thing  other thing
0          1           0.1           a
1          2           0.2           e
2          3           1.0           i
3          4           2.0           o

Comments

7

Even though it's an old question, you can also use loc and iloc:

frame = frame.loc[:, ['column I want first', 'column I want second', "other thing"]]

frame = frame.iloc[:, [1, 3, 2]]

1 Comment

This is a great one if you want to do it by position, not name of column
4
df = df.reindex(columns=["A", "B", "C"])

Comments

1

I find this to be the most straightforward and working:

df = pd.DataFrame({
        'one thing':[1,2,3,4],
        'second thing':[0.1,0.2,1,2],
        'other thing':['a','e','i','o']})

df = df[['one thing','second thing', 'other thing']]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.