TL; DR

Use

sz = temp['INCOME'].size-1
temp['PCNT_LIN'] = temp['INCOME'].rank(method='max').apply(lambda x: 100.0*(x-1)/sz)

   INCOME    PCNT_LIN
0      78   44.444444
1      38   11.111111
2      42   22.222222
3      48   33.333333
4      31    0.000000
5      89   55.555556
6      94   66.666667
7     102   77.777778
8     122  100.000000
9     122  100.000000

Answer

It is actually very simple, once your understand the mechanics. When you are looking for percentile of a score, you already have the scores in each row. The only step left is understanding that you need percentile of numbers that are less or equal to the selected value. This is exactly what parameters kind='weak' of scipy.stats.percentileofscore() and method='average' of DataFrame.rank() do. In order to invert it, run Series.quantile() with interpolation='lower'.

So, the behavior of the scipy.stats.percentileofscore(), Series.rank() and Series.quantile() is consistent, see below:

In[]:
temp = pd.DataFrame([  78, 38, 42, 48, 31, 89, 94, 102, 122, 122], columns=['INCOME'])
temp['PCNT_RANK']=temp['INCOME'].rank(method='max', pct=True)
temp['POF']  = temp['INCOME'].apply(lambda x: scipy.stats.percentileofscore(temp['INCOME'], x, kind='weak'))
temp['QUANTILE_VALUE'] = temp['PCNT_RANK'].apply(lambda x: temp['INCOME'].quantile(x, 'lower'))
temp['RANK']=temp['INCOME'].rank(method='max')
sz = temp['RANK'].size - 1 
temp['PCNT_LIN'] = temp['RANK'].apply(lambda x: (x-1)/sz)
temp['CHK'] = temp['PCNT_LIN'].apply(lambda x: temp['INCOME'].quantile(x))

temp

Out[]:
   INCOME  PCNT_RANK    POF  QUANTILE_VALUE  RANK  PCNT_LIN    CHK
0      78        0.5   50.0              78   5.0  0.444444   78.0
1      38        0.2   20.0              38   2.0  0.111111   38.0
2      42        0.3   30.0              42   3.0  0.222222   42.0
3      48        0.4   40.0              48   4.0  0.333333   48.0
4      31        0.1   10.0              31   1.0  0.000000   31.0
5      89        0.6   60.0              89   6.0  0.555556   89.0
6      94        0.7   70.0              94   7.0  0.666667   94.0
7     102        0.8   80.0             102   8.0  0.777778  102.0
8     122        1.0  100.0             122  10.0  1.000000  122.0
9     122        1.0  100.0             122  10.0  1.000000  122.0

Now in a column PCNT_RANK you get ratio of values that are smaller or equal to the one in a column INCOME. But if you want the "interpolated" ratio, it is in column PCNT_LIN. And as you use Series.rank() for calculations, it is pretty fast and will crunch you 255M numbers in seconds.


Here I will explain how you get the value from using quantile() with linear interpolation:

temp['INCOME'].quantile(0.11)
37.93

Our data temp['INCOME'] has only ten values. According to the formula from your link to Wiki the rank of 11th percentile is

rank = 11*(10-1)/100 + 1 = 1.99

The truncated part of the rank is 1, which corresponds to the value 31, and the value with the rank 2 (i.e. next bin) is 38. The value of fraction is the fractional part of the rank. This leads to the result:

 31 + (38-31)*(0.99) = 37.93

For the values themselves, the fraction part have to be zero, so it is very easy to do the inverse calculation to get percentile:

p = (rank - 1)*100/(10 - 1)

I hope I made it more clear.

Answer from igrinis on Stack Overflow
Top answer
1 of 3
48

TL; DR

Use

sz = temp['INCOME'].size-1
temp['PCNT_LIN'] = temp['INCOME'].rank(method='max').apply(lambda x: 100.0*(x-1)/sz)

   INCOME    PCNT_LIN
0      78   44.444444
1      38   11.111111
2      42   22.222222
3      48   33.333333
4      31    0.000000
5      89   55.555556
6      94   66.666667
7     102   77.777778
8     122  100.000000
9     122  100.000000

Answer

It is actually very simple, once your understand the mechanics. When you are looking for percentile of a score, you already have the scores in each row. The only step left is understanding that you need percentile of numbers that are less or equal to the selected value. This is exactly what parameters kind='weak' of scipy.stats.percentileofscore() and method='average' of DataFrame.rank() do. In order to invert it, run Series.quantile() with interpolation='lower'.

So, the behavior of the scipy.stats.percentileofscore(), Series.rank() and Series.quantile() is consistent, see below:

In[]:
temp = pd.DataFrame([  78, 38, 42, 48, 31, 89, 94, 102, 122, 122], columns=['INCOME'])
temp['PCNT_RANK']=temp['INCOME'].rank(method='max', pct=True)
temp['POF']  = temp['INCOME'].apply(lambda x: scipy.stats.percentileofscore(temp['INCOME'], x, kind='weak'))
temp['QUANTILE_VALUE'] = temp['PCNT_RANK'].apply(lambda x: temp['INCOME'].quantile(x, 'lower'))
temp['RANK']=temp['INCOME'].rank(method='max')
sz = temp['RANK'].size - 1 
temp['PCNT_LIN'] = temp['RANK'].apply(lambda x: (x-1)/sz)
temp['CHK'] = temp['PCNT_LIN'].apply(lambda x: temp['INCOME'].quantile(x))

temp

Out[]:
   INCOME  PCNT_RANK    POF  QUANTILE_VALUE  RANK  PCNT_LIN    CHK
0      78        0.5   50.0              78   5.0  0.444444   78.0
1      38        0.2   20.0              38   2.0  0.111111   38.0
2      42        0.3   30.0              42   3.0  0.222222   42.0
3      48        0.4   40.0              48   4.0  0.333333   48.0
4      31        0.1   10.0              31   1.0  0.000000   31.0
5      89        0.6   60.0              89   6.0  0.555556   89.0
6      94        0.7   70.0              94   7.0  0.666667   94.0
7     102        0.8   80.0             102   8.0  0.777778  102.0
8     122        1.0  100.0             122  10.0  1.000000  122.0
9     122        1.0  100.0             122  10.0  1.000000  122.0

Now in a column PCNT_RANK you get ratio of values that are smaller or equal to the one in a column INCOME. But if you want the "interpolated" ratio, it is in column PCNT_LIN. And as you use Series.rank() for calculations, it is pretty fast and will crunch you 255M numbers in seconds.


Here I will explain how you get the value from using quantile() with linear interpolation:

temp['INCOME'].quantile(0.11)
37.93

Our data temp['INCOME'] has only ten values. According to the formula from your link to Wiki the rank of 11th percentile is

rank = 11*(10-1)/100 + 1 = 1.99

The truncated part of the rank is 1, which corresponds to the value 31, and the value with the rank 2 (i.e. next bin) is 38. The value of fraction is the fractional part of the rank. This leads to the result:

 31 + (38-31)*(0.99) = 37.93

For the values themselves, the fraction part have to be zero, so it is very easy to do the inverse calculation to get percentile:

p = (rank - 1)*100/(10 - 1)

I hope I made it more clear.

2 of 3
2

This seems to work:

A = np.sort(temp['INCOME'].values)
np.interp(sample, A, np.linspace(0, 1, len(A)))

For example:

>>> temp.INCOME.quantile(np.interp([37.5, 38, 122, 121], A, np.linspace(0, 1, len(A))))
0.103175     37.5
0.111111     38.0
1.000000    122.0
0.883333    121.0
Name: INCOME, dtype: float64

Please note that this strategy only makes sense if you want to query a large enough number of values. Otherwise the sorting is too expensive.

🌐
Medium
medium.com › @amit25173 › understanding-percentiles-in-pandas-369166d19e76
Understanding Percentiles in Pandas | by Amit Yadav | Medium
March 6, 2025 - If you want to include them, you can set dropna=False, but this will likely return NaN as the result. Can I calculate percentiles for grouped data? Answer: Yes! You can use groupby() along with quantile() to calculate percentiles within groups.
🌐
datagy
datagy.io › home › pandas tutorials › data analysis in pandas › pandas quantile: calculate percentiles of a dataframe
Pandas Quantile: Calculate Percentiles of a Dataframe • datagy
April 16, 2023 - This has a big impact on legacy ... the value(s) of quantiles to calculate · axis=[0]: the axis to calculate the percentiles on (0 for row-wise and 1 for column-wise)...
🌐
GeeksforGeeks
geeksforgeeks.org › percentile-rank-of-a-column-in-a-pandas-dataframe
Percentile rank of a column in a Pandas DataFrame - GeeksforGeeks
August 17, 2020 - Let us see how to find the percentile rank of a column in a Pandas DataFrame. We will use the rank() function with the argument pct = True to find the percentile rank.
Top answer
1 of 5
45

To find the percentile of a value relative to an array (or in your case a dataframe column), use the scipy function stats.percentileofscore().

For example, if we have a value x (the other numerical value not in the dataframe), and a reference array, arr (the column from the dataframe), we can find the percentile of x by:

from scipy import stats
percentile = stats.percentileofscore(arr, x)

Note that there is a third parameter to the stats.percentileofscore() function that has a significant impact on the resulting value of the percentile, viz. kind. You can choose from rank, weak, strict, and mean. See the docs for more information.

For an example of the difference:

>>> df
   a
0  1
1  2
2  3
3  4
4  5

>>> stats.percentileofscore(df['a'], 4, kind='rank')
80.0

>>> stats.percentileofscore(df['a'], 4, kind='weak')
80.0

>>> stats.percentileofscore(df['a'], 4, kind='strict')
60.0

>>> stats.percentileofscore(df['a'], 4, kind='mean')
70.0

As a final note, if you have a value that is greater than 80% of the other values in the column, it would be in the 80th percentile (see the example above for how the kind method affects this final score somewhat) not the 20th percentile. See this Wikipedia article for more information.

2 of 5
5

Probably very late but still

df['column_name'].describe()

will give you the regular 25, 50 and 75 percentile with some additional data but if you want percentiles for some specific values then

df['column_name'].describe(percentiles=[0.1, 0.2, 0.3, 0.5])

This will give you 10th, 20th, 30th and 50th percentiles. You can give as many values as you want.

The resulting object can be accessed like a dict:

desc = df['column_name'].describe(percentiles=[0.1, 0.2, 0.3, 0.5])
print(desc)
print(desc['10%'])
🌐
Enterprise DNA
blog.enterprisedna.co › pandas-percentile-calculate-percentiles-of-a-dataframe
Enterprise DNA: We Help Businesses Put Data and AI to Work
Learn data and AI skills on the platform, bring us in on a project, or run a managed Omni Command Centre. 220K+ professionals trained, 1,500+ companies impacted globally.
Find elsewhere
🌐
Data Science Parichay
datascienceparichay.com › home › blog › calculate percentile in python
Calculate Percentile in Python - Data Science Parichay
October 9, 2021 - You can also apply the same function on a pandas dataframe to get the nth percentile value for every numerical column in the dataframe. # get the 95th percentile value of each numerical column df.quantile(0.95)
🌐
Statology
statology.org › home › how to calculate percentile rank in pandas (with examples)
How to Calculate Percentile Rank in Pandas (With Examples)
August 30, 2022 - The following code shows how to calculate the percentile rank of each value in the points column, grouped by team:
🌐
GeeksforGeeks
geeksforgeeks.org › python › calculate-arbitrary-percentile-on-pandas-groupby
Calculate Arbitrary Percentile on Pandas GroupBy - GeeksforGeeks
July 23, 2025 - One is by using Pandas module and other is using NumPy module. Let us see both these methods. To calculate an arbitrary percentile for each group, you can use the quantile() function in combination with groupby().
🌐
Stack Overflow
stackoverflow.com › questions › 52447233 › how-to-calculate-percentile-score-for-each-row-in-pandas
python - How to calculate percentile score for each row in pandas? - Stack Overflow
September 21, 2018 - I'm trying to calculate the speed rank of drivers by looking at his/her past 20 race. However, i need to get get current value and rolling values to function. Here what i did so far: def set_rank(x, y): return stats.percentileofscore(x,y) df['Rank'] = df['SpeedRank'].rolling(20).apply(lambda x: set_rank(x, df['SpeedRank']), raw=True) The problem is y how can i send value of corresponding row to the function?
🌐
Statology
statology.org › home › how to calculate percentiles in python (with examples)
How to Calculate Percentiles in Python (With Examples)
November 3, 2020 - The nth percentile of a dataset is the value that cuts off the first n percent of the data values when all of the values are sorted from least to greatest.
🌐
DataScience Made Simple
datasciencemadesimple.com › home › percentile rank of a column in pandas python – (percentile value)
Percentile rank of a column in pandas python - (percentile value) - DataScience Made Simple
November 15, 2019 - import pandas as pd import numpy ... Percentile rank of the column (Mathematics_score) is computed using rank() function and with argument (pct=True), and stored in a new column namely “percentile_rank” as shown ...
🌐
Arab Psychology
scales.arabpsychology.com › home › how to calculate percentile rank in pandas (with examples)
How To Calculate Percentile Rank In Pandas (With Examples)
November 25, 2025 - Pandas has a built-in method for calculating percentile ranks called .rank(). It takes a numerical column of data and returns the percentile rank of each value in the column, from 0 to 100. It is simple to use and can be applied to many different types of data.
🌐
GeeksforGeeks
geeksforgeeks.org › python › pandas-dataframe-quantile
Pandas DataFrame quantile() Method | Find Quantile Values - GeeksforGeeks
July 11, 2025 - Let's see some examples of how to find values of a given quantile using the quantile() function of the Pandas library. Below are the Python codes that illustrates the working of the quantile method on a DataFrame with output.