I'd like to calculate the percentile of each value in a list (or numpy array), weighted by weights in another list. For example, given some f
I'd like:
x = [1, 2, 3, 4]
weights = [2, 2, 3, 3]
f(x, weights)
to yield [20, 40, 70, 100]
.
I can calculate the unweighted percentile for a single item using
from scipy import stats
stats.percentileofscore(x, 3)
# 75.0
Per Map each list value to its corresponding percentile I can also calculate this for each using
[stats.percentileofscore(x, a, 'rank') for a in x]
# [25.0, 50.0, 75.0, 100.0]
And per Weighted version of scipy percentileofscore I can calculate a single item's weighted percentile using:
def weighted_percentile_of_score(x, weights, score, kind='weak'):
npx = np.array(x)
npw = np.array(weights)
if kind == 'rank': # Equivalent to 'weak' since we have weights.
kind = 'weak'
if kind in ['strict', 'mean']:
indx = npx < score
strict = 100 * sum(npw[indx]) / sum(weights)
if kind == 'strict':
return strict
if kind in ['weak', 'mean']:
indx = npx <= score
weak = 100 * sum(npw[indx]) / sum(weights)
if kind == 'weak':
return weak
if kind == 'mean':
return (strict + weak) / 2
Called as:
weighted_percentile_of_score(x, weights, 3)) # 70.0 as desired.
How do I do this (efficiently) for each item in the list?