Процентили Numpy с линейной интерполяцией - неправильное значение?

Формула линейной интерполяции для процентилей:

линейный: i + (j - i) * фракция, где фракция — это дробная часть индекса, окруженная i и j.

Предположим, у меня есть этот список с 16 наблюдениями:

test = [0, 1, 5, 5, 5, 6, 6, 7, 7, 8, 11, 12, 21, 23, 23, 24]

Я передаю его как массив numpy и вычисляю 85-й процентиль, используя линейную интерполяцию.

np_test = np.asarray(test)
np.percentile(np_test, 85, interpolation = 'linear')

В результате я получаю 22,5. Однако я не думаю, что это правильно. Индекс 85-го процентиля равен 0,85 * 16 = 13,6. Таким образом, дробная часть равна 0,6. 13-е значение равно 21, поэтому i = 21. 14-е значение равно 23, поэтому j = 23. Тогда линейная формула должна дать:

21 + (23 - 21) * .6 = 21 + 2 * .6 = 21 + 1.2 = 22.2

Правильный ответ: 22,2. Почему вместо этого я получаю 22,5?


person jerbear    schedule 15.02.2018    source источник


Ответы (1)


len(test) равно 16, но расстояние между последним элементом и первым элементом меньше на 1, то есть d=16-1=15-0=15. Следовательно, индекс 85-го процентиля равен d*0.85 = 15*0.85 = 12.75. test[12] = 21 и test[13] = 23. Следовательно, используя линейную интерполяцию для дробной части, мы получаем: 21 + 0.75 * (23 - 21) = 22.5. Правильный ответ: 22,5.

Из раздела Примечания документации numpy.percentile():

Для вектора V длины N q-й процентиль V — это значение q/100 пути от минимума до максимума в отсортированной копии V.

Ключевым здесь, на мой взгляд, является "путь от минимума к максимуму". Допустим, мы нумеруем элементы от 1 до 16. Тогда «позиция» первого элемента равна 1, а «позиция» (вдоль «координатной оси индексов») последнего элемента в test равна 16. Следовательно, расстояние между ними 16-1=15.

person AGN Gazer    schedule 15.02.2018
comment
Почему он идет по максимальному индексу? Разве это не должно происходить по количеству наблюдений? Есть ли способ обойти это? - person jerbear; 15.02.2018
comment
@JerinVarghese Если вы хотите использовать другое определение, например, ожидая, что эта функция будет использовать количество элементов вместо расстояния между ними, я могу представить, что вы могли бы добавить число, которое меньше, чем любой другой элемент в массиве/списке, для например, test.append(min(test)-1). Это должно сработать. - person AGN Gazer; 15.02.2018
comment
@JerinVarghese Добро пожаловать! Просто будьте осторожны, чтобы не использовать q<1/N, потому что тогда будет интерполяция между min(test) и произвольным значением min(test)-1 (это произвольно, потому что вы могли бы использовать min(test)-100 для реализации трюка). Поэтому результатом будет мусор. - person AGN Gazer; 15.02.2018