Sorting by absolute value without changing the data

PythonPandasSortingDataframe

Python Problem Overview


I'm looking for a simple way to sort a pandas dataframe by the absolute value of a particular column, but without actually changing the values within the dataframe. Something similar to sorted(df, key=abs). So if I had a dataframe like:

    a	b
0	1	-3
1	2	5 
2	3	-1
3	4	2
4	5	-9

The resultant sorted data when sorting on 'b' would look like:

    a	b
2	3	-1
3	4	2
0	1	-3
1	2	5 
4	5	-9

Python Solutions


Solution 1 - Python

UPDATE

Since 0.17.0 order and sort have been deprecated (thanks @Ruggero Turra), you can use sort_values to achieve this now:

In[16]:

df.reindex(df.b.abs().sort_values().index)
Out[16]: 
   a  b
2  3 -1
3  4  2
0  1 -3
1  2  5
4  5 -9

Solution 2 - Python

Perfect Simple Solution with Pandas > V_1.1.0:

Use the parameter key in the sort_values() function:

import pandas as pd
ttt = pd.DataFrame({'A': ['a', 'b', 'c', 'd', 'e', 'f'], 'B': [-3, -2, -1, 0, 1, 2]})

ttt.sort_values(by='B', key=abs)

will yield:

	A	B
3	d	0
2	c	-1
4	e	1
1	b	-2
5	f	2
0	a	-3

Solution 3 - Python

Towards more idiomatic pandas: Use argsort

A cleaner approach would be to call Series.argsort on the absolute values, and then index:

df.iloc[df['b'].abs().argsort()]

   a  b
2  3 -1
3  4  2
0  1 -3
1  2  5
4  5 -9

If you need to reset the index, use Series.reset_index,

df.iloc[df['b'].abs().argsort()].reset_index(drop=True)

   a  b
0  3 -1
1  4  2
2  1 -3
3  2  5
4  5 -9

Lastly, since argsort does not have an ascending parameter to specify ascending/descending order, you will need to negate df['b'].abs() to sort by descending order.

df.iloc[(-df['b'].abs()).argsort()]

   a  b
4  5 -9
1  2  5
0  1 -3
3  4  2
2  3 -1

You can do this with NumPy as well—use np.abs and ndarray.argsort.

df.iloc[np.abs(df['b'].values).argsort()]

   a  b
2  3 -1
3  4  2
0  1 -3
1  2  5
4  5 -9

Or, for descending order,

df.iloc[(-np.abs(df['b'].values)).argsort()]

   a  b
4  5 -9
1  2  5
0  1 -3
3  4  2
2  3 -1

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionafinitView Question on Stackoverflow
Solution 1 - PythonEdChumView Answer on Stackoverflow
Solution 2 - PythonLucecpknView Answer on Stackoverflow
Solution 3 - Pythoncs95View Answer on Stackoverflow