Numpy: Перцентильные методы реструктуризации

Созданный на 12 мар. 2018  ·  53Комментарии  ·  Источник: numpy/numpy

Как показано на странице Википедии: https://en.wikipedia.org/wiki/Percentile#The_nearest -rank_method

00 - Bug 01 - Enhancement high

Все 53 Комментарий

Думаю, это уже существует? На примере из Википедии:

>>> np.percentile(15, 20, 35, 40, 50], [5, 30, 40, 50, 100], interpolation='lower')
array([15, 20, 20, 35, 50])

Это не. Посмотрите на пример 2 на странице википедии:

>>> np.percentile([3, 6, 7, 8, 8, 10, 13, 15, 16, 20], [25,50,75,100], interpolation='lower')
array([ 7,  8, 13, 20])

Когда должно быть [7,8,15,20]

Точно так же не получается в третьем примере

Ближайшее звучит очень похоже на «ближайший»? Хотя всегда есть еще один вопрос, как именно работают границы.
РЕДАКТИРОВАТЬ: То есть, где именно считаются 0 и 100, в точке данных или до точки данных? (то есть IIRC, все равно тут много досадных сложностей)

не хочу это читать, я думаю, разница может быть в параметре C ниже, поэтому, если кто-то, кто знает это, захочет добавить это ....

Честно говоря, я думаю, что добавление параметра C, вероятно, действительно было бы хорошо. Но в основном документация была бы лучше, и нужен кто-то, кто действительно разбирается в этом ...

Я не знаю, имеет ли это какое-либо отношение к параметру C, хотя я согласен с тем, что вариант его выбора может быть желательным.

Я нашел еще одну ветку, которая случайно подняла эту проблему (декабрь 2016 г.). Кажется, что алгоритм, который я ищу (и который википедия называет ближайшим рангом), упоминается в этой часто цитируемой статье Хайндмана-Фана (H&F) как старейшее и наиболее изученное определение процентиля (это было то, которое я изучил в Статистический курс). Это прерывистая функция, поэтому я думаю, что параметр C здесь не применяется (я могу ошибаться).

Вот как это будет выглядеть на фоне других опций, предоставляемых numpy, которые интуитивно кажутся вычисляющими похожую вещь (например, «ниже», «ближе всего»):

percentiles

На первый взгляд, это похоже на параметр C, ближайшая кривая более растянута, чем кривая H&F, чего и следовало ожидать, поскольку numpy использует 1 и, очевидно, H&F использует 0.

Если вам нужны доказательства. Повторите все это с теми же значениями, повторенными 1000 раз, я предполагаю, что они сойдутся.
РЕДАКТИРОВАТЬ: Или, может быть, нет, у вас нет терпения или времени, чтобы действительно подумать об этом. Но я все еще думаю, что это упоминается в Википедии о параметре C, поэтому, пожалуйста, докажите, что я ошибаюсь :)

Такой график был бы отличным дополнением к документации по процентилям.

изменить: предпочтительно тот, который показывает открытость / закрытость разрывов

Примечание для читателей: чтобы сохранить управляемость этой цепочки, я пометил все обсуждения ниже о добавлении этого графика в документы как «решенные». График теперь находится внизу https://numpy.org/devdocs/reference/generated/numpy.percentile.html.

@ eric-wieser Я не против построить этот график. Я вернусь с чем-то позже сегодня, я могу разместить это здесь?

@seberg Я буду честен здесь, я не знаю, как вычисляется интерполяция на основе C-параметра. Что заставляет меня думать, что это не связано, так это то, что C-параметр обсуждается только в разделе линейной интерполяции (Википедия), и и в Википедии, и в статье Hyndmand & Fan алгоритм, который я запрашивал, обсуждается отдельно от разделов, посвященных интерполяции.

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

Даже если есть, нужно ли использовать этот способ для этого? Изменение «странного» параметра для получения наиболее распространенного определения процентиля не кажется лучшим способом реализовать его imho.

@ ricardoV94 , возможно, но вы не можете просто изменить значения по умолчанию, какими бы плохими они ни были. Мы могли бы выставить что-то вроде method = "H&K" для одновременного переопределения обоих параметров.

Параметры C - это то место, где вы определяете 0% и 100% по отношению к точкам данных (в точке данных или нет и т. Д.). Как параметр C в Википедии, он вполне может быть только для интерполяции, но я уверен, что та же проблема вызывает разницу здесь. C , конечно, сомнительно, собственное имя может быть чем-то вроде range = 'min-max' или range = 'extrapolated' или, возможно, чем-то совершенно другим. Как я уже сказал, переделайте графики с большим количеством точек данных (возможно, с небольшим шумом), и я думаю, вы увидите, что они сходятся, поскольку определение диапазона становится менее очевидным.

@seberg Меня устраивает method = "H&K" или, может быть, method = "classic". Interpolation = "none" тоже может иметь смысл.

Я не уверен, каков механизм включения изображений в документацию и есть ли прецедент для этого.

Я знаю, что вы можете запускать код matplotlib в документации, как мы это делаем в других местах, что также гарантирует, что он останется синхронизированным с реальностью.

Хорошо, в этом случае я подумаю о лучшем образе кода.

Наиболее проблематичной частью являются открытые и закрытые маркеры разрыва, поскольку в matplotlib нет встроенной функции для этого (afaik). В этом случае их жесткое кодирование не имело бы смысла.

Может быть, тогда пропустите их. Было бы хорошо, если бы у matplotlib была автоматическая поддержка для них.

Надеюсь, у кого-то будет лучшее предложение, которое все еще элегантно в отношении разрыва.

import matplotlib.pyplot as plt

a = [0,1,2,3]
p = np.arange(101)

plt.step(p, np.percentile(a, p, interpolation='linear'), label='linear')
plt.step(p, np.percentile(a, p, interpolation='higher'), label='higher', linestyle='--')
plt.step(p, np.percentile(a, p, interpolation='lower'), label='lower', linestyle='--')
plt.step(p, np.percentile(a, p, interpolation='nearest'), label='nearest', linestyle='-.',)
plt.step(p, np.percentile(a, p, interpolation='midpoint'), label='midpoint', linestyle='-.',)

plt.title('Interpolation methods for list: ' + str(a))
plt.xlabel('Percentile')
plt.ylabel('List item returned')
plt.yticks(a)
plt.legend()

Image

Я думаю, что interpolation = 'linear' должна быть обычной, а не ступенчатой ​​линией, но в остальном выглядит хорошо. Можете ли вы сделать PR, добавив это в документы?

Фактически, step обычно вызывает артефакты, вводящие в заблуждение, поэтому я был бы склонен избегать этого. linspace(0, 100, 60) даст более точные промежуточные координаты

Понятия не имею, как сделать пиар.

Не стесняйтесь делать это со своей учетной записью, добавляя или обсуждая предлагаемые изменения.

Я думаю, вы можете изменить C на что-то вроде этого (протестируйте на чем-нибудь). Вызовите функцию для ваших процентилей, а затем подключите ее к версии numpy (которая использует C = 1, что не является операцией, за исключением исправления вне границ процентилей прямо сейчас):

def scale_percentiles(p, num, C=0):
     """
     p : float
          percentiles to be used (within 0 and 100 inclusive)
     num : int
         number of data points.
     C : float
         parameter C, should be 0, 0.5 or 1. Numpy uses 1, matlab 0.5, H&K is 0.
     """
     p = np.asarray(p)
     fact = (num-1.+2*C)/(num-1)
     p *= fact
     p -= 0.5 * (fact-1) * 100
     p[p < 0] = 0
     p[p > 100] = 100
     return p

И вуаля, с "ближайшим" вы получите свой "H&F", а с linear вы получите сюжет из Википедии. (в ожидании того, что я что-то не так, но я почти уверен, что понял правильно).

Как я уже сказал, разница в том, где вы размещаете точки данных от 0 до 100 (равномерно) по отношению к последней точке. Для C = 1 вы помещаете min (данные) в 0-й процентиль и т. Д. Я понятия не имею, «что имеет больше смысла», это, вероятно, имеет значение для общего взгляда. Я думаю, имя, включающее 1 и исключающее 0, имеет некоторый смысл (когда вы думаете об общем диапазоне процентилей, поскольку исключительный возможный диапазон находится за пределами диапазона данных). C = 1/2 также является исключительным в этом смысле.

Я бы за добавление параметра C, но я бы хотел, чтобы кто-нибудь придумал описательное имя, если это возможно. Я также не возражал бы против чего-то вроде "метода" или чего-то такого, чтобы сделать лучшие значения по умолчанию очевидными (комбинация интерполяции + C). Или вы, по сути, решаете, что большинство комбинаций никогда не используются и бесполезны, тогда хорошо ....

В конце концов, моя проблема: я хочу, чтобы статистик сказал мне, какие методы имеют консенсус (у R есть кое-что, но в последний раз, когда кто-то приходил сюда, это была просто копия прошлого документа R или аналогичного, без установки в контекст numpy в все, разумеется, для широкой аудитории это было бесполезно, ссылки на статьи были бы полезнее).

Я не хочу читать эту статью о H&F (честно говоря, она тоже не выглядит привлекательной для чтения), но я думаю, что вы могли бы взглянуть на нее и с точки зрения поддержки. Numpy «ближайшая» (или любая другая) версия не имеет идентичной поддержки (в процентилях) для каждой точки данных, H&F имеет равную поддержку для «ближайшей» и, возможно, для средней точки это будет C = 1/2, не уверен.
Я все время повторяю, я не знаю, является ли такой аргумент поддержки (против C = 1, такого как numpy) реальной причиной.

РЕДАКТИРОВАТЬ: средняя точка имеет одинаковую поддержку (для области между точками данных, а не для самой точки) в numpy, поэтому с "C = 1"

@seberg Мне кажется, это не работает. Можете ли вы опубликовать свой код, показывающий, что он работает?

Что ж, я ошибся знаком в том коде, так что все было наоборот (C = 0, а не C = 1):

def scale_percentiles(p, num, C=0):
     """
     p : float
          percentiles to be used (within 0 and 100 inclusive)
     num : int
         number of data points.
     C : float
         parameter C, should be 0, 0.5 or 1. Numpy uses 1, matlab 0.5, H&F is 0.
     """
     p = np.asarray(p)
     fact = (num+1.-2*C)/(num-1)
     p *= fact
     p -= 0.5 * (fact-1) * 100
     p[p < 0] = 0
     p[p > 100] = 100
     return p
plt.figure()
plt.plot(np.percentile([0, 1, 2, 3], scale_percentiles(np.linspace(0, 100, 101), 5, C=0), interpolation='nearest'))
plt.plot(np.percentile([0, 1, 2, 3], scale_percentiles(np.linspace(0, 100, 101), 5, C=1), interpolation='nearest'))
plt.figure()
plt.plot(np.percentile([15, 20, 35, 40, 50], scale_percentiles(np.linspace(0, 100, 101), 5, C=1), interpolation='linear'))
plt.plot(np.percentile([15, 20, 35, 40, 50], scale_percentiles(np.linspace(0, 100, 101), 5, C=0.5), interpolation='linear'))
plt.plot(np.percentile([15, 20, 35, 40, 50], scale_percentiles(np.linspace(0, 100, 101), 5, C=0), interpolation='linear'))

@seberg Близко, но еще не a = [0,1,2,3] и percentiles = [25, 50, 75, 100] , np.percentile (a, scale_percentiles(percentiles, len(a), C=0), interpolation='nearest) возвращает [0, 2, 3, 3] , тогда как должно возвращать [0,1,2,3] .

Мне пришлось сделать процентили списка dtype=np.float иначе ваша функция выдала бы ошибку, но я не думаю, что это проблема.

Функция для классического метода проста:
Процентиль / 100 * N -> Если это целое число, которое является индексом, в противном случае используйте потолок в качестве индекса.

Несмотря на это, аргумент C, похоже, работает так, как ожидалось, поэтому его можно реализовать, если люди захотят использовать его для интерполяции. Я все еще хотел бы, чтобы method = 'classic' или interpolation = 'none' работал бы как метод из Википедии.

Для отладки это моя уродливая безумная реализация классического метода:

def percentile (arr, p):
    arr = sorted(arr)

    index = p /100 * len(arr)

    # If index is a whole number, and larger than zero, subtract one unit (due to 0-based indexing)
    if index%1 < 0.0001 and index//1 > 0:
        index -= 1

    return arr[int(index)]

и более numpythonic:

def indexes_classic(percentiles, set_size):
    percentiles = np.asarray(percentiles)

    indexes = percentiles / 100* set_size
    indexes[np.isclose(indexes%1, 0)] -= 1
    indexes = np.asarray(indexes, dtype=np.int)
    indexes[indexes < 0] = 0
    indexes[indexes > 100] = 100

    return indexes

Эти различия звучат как проблемы с плавающей запятой / округлением (которые вы
кажется, в курсе), и, возможно, мое предположение с C = 0 было неверным, и вы хотите
С = 0,5.
Я хотел сказать, откуда взялась разница («параметр C»
ИМО, хотя, вероятно, есть веские причины не любить многих
комбинации). Это было не для того, чтобы дать вам / реализовать обходной путь.

Что же касается «классического» метода, то мне откровенно безразлично, какой классический
должно быть. Насколько я знаю, "классический" означает "довольно много
люди его используют ".

С точки зрения решения, мое первое впечатление - это "классический" или что-то еще.
name, просто добавляет еще один запутанный вариант с нечетким названием. я надеюсь
что это обсуждение могло бы пойти в направлении фактического создания всех
хорошие (общие) варианты доступны пользователям в чистом и прозрачном
путь. Лучше всего так, чтобы люди действительно могли понять.

Можно добавить еще один метод, но, честно говоря, он мне нравится только наполовину. Когда мы
последний добавил дополнительные методы (не помню, что именно изменилось) Я
уже задержался и надеялся, что кто-то вскочит и разберется
что у нас должно быть. Излишне говорить, что на самом деле этого никогда не было. И сейчас
Я пытаюсь указать на различия и посмотреть, как это может быть
с тем, что у нас есть сейчас.

Итак, мое впечатление такое (возможны проблемы с округлением и точным
процентильные совпадения) у нас есть (наверное, слишком) много вариантов "интерполяции"
и потребует "параметр C" или как вы хотите его назвать
уметь делать практически все.
И я был бы очень рад, если бы кто-нибудь рассказал мне, как все
(часто) "Методы" попадают в эти категории, кажется, что
более чем C = 0,0.5,1 существуют даже, а возможно, некоторые даже вне этих
параметры....

Возможно, я иду не по той полосе, но добавляю "Method1" с
непонятное название, которое никому не говорит, чем оно отличается от
другие методы мне не кажутся полезными (кроме тех, кто
оказывается, уже знает имя "Метод1" и ищет его. И
пожалуйста, не говорите, что "классика" очевидна, есть
слишком большая разница в реализациях.

Другой способ - использовать устаревшую "интерполяцию", но иметь список
методов также гораздо менее приятен, чем намек на "линейную интерполяцию"
сказать, что это не пошаговое поведение и т. д. И если мы пойдем этим путем,
Мне все еще нужен разумный обзор.

Вам не обязательно этого делать, но если мы хотим добавить новый метод, нам понадобится
способ его добавить, что никого не смущает еще больше и понятен!

Тогда позвольте мне резюмировать это:

1) Прямо сейчас numpy предлагает только один полезный метод: interpolation = 'linear', а остальные - это просто небольшие вариации вокруг него, которые, похоже, действительно никем не используются. В других пакетах есть еще много подходящих опций.

2) Добавление других значений для C = 0 или C = 0,5 имеет для меня смысл. Все методы интерполяции могут работать в сочетании с ними, хотя, опять же, они, вероятно, никогда не будут использоваться.

3) Если одна из комбинаций между методами интерполяции и аргументом C позволяет воспроизвести классический метод (ссылка, википедия и мой личный опыт подтверждают, что это наиболее распространенный метод), то я доволен этим. В документации можно указать, что такая комбинация дает классический метод без интерполяции. Я не уверен, что это просто из-за проблем с точностью поплавка, но я ценю ваши усилия по решению этой проблемы более комплексным способом!

4) Если ни одна из комбинаций не дает одинакового результата, я думаю, что имеет смысл использовать другой метод. Возможно, это вызовет интерполяцию = 'none'.

В итоге: текущие параметры numpy.percentile кажутся довольно запутанными и ограниченными. В упомянутой выше статье содержится хороший обзор других полезных методов. Вместе со страницей википедии они могли бы стать отправной точкой для разработки более исчерпывающего и полезного набора параметров для numpy.percentile. Надеюсь, кто-то захочет поработать над этой задачей.

Имеет ли смысл текущее «ближайшее» в некоторых / любых случаях? Если метод интервала ("C") или что-то еще имеет такое большое значение для линейной интерполяции / дробного материала, я, может быть, просто удивлен, что никто никогда не делал этого для нефракционных приближений ?! Так ли важна постоянная поддержка и есть ли причина отказаться от обратного аргумента CDF для методов интерполяции?

Комбинации бесполезны, если они не понятны, а часто используемые легко найти, поэтому я сомневаюсь в этом. Для интерполяции, похоже, существует много вариантов (например, http://mathworld.wolfram.com/Quantile.html Q4 – Q9, я думаю, что документация R практически идентична, но я думаю, что она, вероятно, не полная, например, Matlab ...), хотя Понятия не имею, все ли они имеют смысл;).

Дело в том, что «интерполяция» указывает на то, что делать между точно определенными точками, но есть много (как ни странно) способов разместить эти точки, по крайней мере, при использовании «линейной интерполяции», поэтому добавление к ней кажется плохим подходом. Вы хотели "ближайший ранг", который звучит много (и по духу) interpolation = "Ближайший", но выбор точной "позиции построения" кажется "нестандартным", поэтому угадать будет невозможно и, следовательно, плохой выбор.

Тогда я бы даже предпочел резко отказаться от всего (кроме, возможно, линейного).

Но, если мы принизить, я хочу , чтобы получить его 100% право, и что , возможно , потребуется немного больше ясности относительно того , что существует, что должно существовать и что должно определенно не существует.

Я полностью с тобой согласен

@ ricardoV94 : есть ли у вас какие-либо мнения об определениях linear для случая взвешенного квантиля, предложенного в # 9211? Там есть графики в таком же стиле.

Возможно, @ ricardoV94 сможет это прокомментировать (это было бы круто), но я думаю, что проблема довольно ортогональна. Веса, вероятно, являются просто весами частотного типа, если предположить, что нет других разумно определенных весов для процентиля (я не понимаю, как), не должно быть двусмысленности при их реализации, но я не знаю точно.

Вы также можете попробовать связаться с josef-pkt по поводу этого PR и надеяться, что он быстро прокомментирует, считает ли он это хорошей идеей / правильным.

Если кто-то захочет взять это отсюда, я написал неоптимизированную функцию, которая вычисляет
9 методов оценки процентилей / квантилей, описанных Hyndman and Fan (1996), а также используемых в R.

Метод 1 соответствует «классическому методу ближайшего ранга», описанному в Википедии . Метод 7 эквивалентен текущей реализации Numpy (интерполяция = 'linear'). Остальные методы интерполяции Numpy не включены (и в любом случае они не кажутся полезными).

def percentile(x, p, method=7):
    '''
    Compute the qth percentile of the data.

    Returns the qth percentile(s) of the array elements.

    Parameters
    ----------
    x : array_like
        Input array or object that can be converted to an array.
    p : float in range of [0,100] (or sequence of floats)
        Percentile to compute, which must be between 0 and 100 inclusive.
    method : integer in range of [1,9]
        This optional parameter specifies one of the nine sampling methods 
        discussed in Hyndman and Fan (1996). 

        Methods 1 to 3 are discontinuous:
        * Method 1: Inverse of empirical distribution function (oldest
        and most studied method).
        * Method 2: Similar to type 1 but with averaging at discontinuities.
        * Method 3: SAS definition: nearest even order statistic.

        Methods 4 to 9 are continuous and equivalent to a linear interpolation 
        between the points (pk,xk) where xk is the kth order statistic. 
        Specific expressions for pk are given below:
        * Method 4: pk=kn. Linear interpolation of the empirical cdf.
        * Method 5: pk=(k−0.5)/n. Piecewise linear function where the knots 
        are the values midway through the steps of the empirical cdf 
        (Popular amongst hydrologists, used by Mathematica?).
        * Method 6: pk=k/(n+1), thus pk=E[F(xk)]. The sample space is divided
        in n+1 regions, each with probability of 1/(n+1) on average
        (Used by Minitab and SPSS).
        * Method 7: pk=(k−1)/(n−1), thus pk=mode[F(xk)]. The sample space
        is divided into n-1 regions (This is the default method of 
        Numpy, R, S, and MS Excell).
        * Method 8: pk=(k−1/3)/(n+1/3), thus pk≈median[F(xk)]. The resulting
        estimates are approximately median-unbiased regardless of the
        distribution of x (Recommended by Hyndman and Fan (1996)).
        * Method 9: k=(k−3/8)/(n+1/4), thus pk≈F[E(xk)]if x is normal (?).
        The resulting estimates are approximately unbiased for the expected 
        order statistics if x is normally distributed (Used for normal QQ plots).

        References:
        Hyndman, R. J. and Fan, Y. (1996) Sample quantiles in statistical packages, 
        American Statistician 50, 361--365.
        Schoonjans, F., De Bacquer, D., & Schmid, P. (2011). Estimation of population
        percentiles. Epidemiology (Cambridge, Mass.), 22(5), 750.

        '''

    method = method-1    
    x = np.asarray(x)
    x.sort()
    p = np.array(p)/100

    n = x.size  
    m = [0, 0, -0.5, 0, 0.5, p, 1-p, (p+1)/3, p/4+3/8][method]

    npm = n*p+m
    j = np.floor(npm).astype(np.int)
    g = npm-j

    # Discontinuous functions
    if method < 3:
        yg0 = [0, 0.5, 0][method]
        y = np.ones(p.size)
        if method < 2:
            y[g==0] = yg0
        else:
            y[(g==0) & (j%2 == 0)] = yg0      
    # Continuous functions
    else:
        y = g

    # Adjust indexes to work with Python
    j_ = j.copy()
    j[j<=0] = 1
    j[j > n] = n
    j_[j_ < 0] = 0
    j_[j_ >= n] = n-1 

    return (1-y)* x[j-1] + y*x[j_]

Таким образом, непрерывные методы также могут быть реализованы более эффективно.

def percentile_continuous(x, p, method=7):
    '''
    Compute the qth percentile of the data.

    Returns the qth percentile(s) of the array elements.

    Parameters
    ----------
    x : array_like
        Input array or object that can be converted to an array.
    p : float in range of [0,100] (or sequence of floats)
        Percentile to compute, which must be between 0 and 100 inclusive.
    method : integer in range of [4,9]
        This optional parameter specifies one of the 5 continuous sampling
        methods discussed in Hyndman and Fan (1996). 
        '''

    x = np.asarray(x)
    x.sort()
    p = np.asarray(p)/100
    n = x.size

    if method == 4:
        r = p * n
    elif method == 5:
        r = p * n + .5
    elif method == 6:
        r = p * (n+1)
    elif method == 7:
        r = p * (n-1) + 1
    elif method == 8:
        r = p * (n+1/3) + 1/3
    elif method == 9:
        r = p * (n+1/4) + 3/8

    index = np.floor(r).astype(np.int)

    # Adjust indexes to work with Python
    index_ = index.copy()
    index[index_ <= 0] = 1
    index[index_  > n] = n
    index_[index_ < 0] = 0
    index_[index_ >= n] = n-1

    i = x[index - 1]
    j = x[index_]

    return i + r%1* (j-i)

Кто-нибудь хочет взять его отсюда? Я не имею права делать это.

Как упоминалось в предыдущем посте, похоже, что текущая реализация квантиля в numpy по умолчанию совпадает с R .

В R :

> quantile(c(15, 20, 35, 40, 50), probs=c(0.05, 0.3, 0.4, 0.5, 1))
  5%  30%  40%  50% 100% 
  16   23   29   35   50 
> quantile(c(3, 6, 7, 8, 8, 10, 13, 15, 16, 20), probs=c(0.25, 0.5, 0.75, 1))
  25%   50%   75%  100% 
 7.25  9.00 14.50 20.00
> quantile(c(3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20), probs=c(0.25, 0.5, 0.75, 1))
 25%  50%  75% 100% 
 7.5  9.0 14.0 20.0 

В np.quantile :

>>> np.quantile([15, 20, 35, 40, 50], q=[0.05, 0.3, 0.4, 0.5, 1])
array([16., 23., 29., 35., 50.])
>>> np.quantile([3, 6, 7, 8, 8, 10, 13, 15, 16, 20], q=[0.25, 0.5, 0.75, 1])
array([ 7.25,  9.  , 14.5 , 20.  ])
>>> np.quantile([3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20], q=[0.25, 0.5, 0.75, 1])
array([ 7.5,  9. , 14. , 20. ])

которые, конечно, не воспроизводят примеры, приведенные в Википедии:
https://en.wikipedia.org/wiki/Percentile

Фактически, если вы перейдете на страницу справки R для квантиля https://www.rdocumentation.org/packages/stats/versions/3.5.0/topics/quantile
вы увидите, что метод R по умолчанию (тип 7) устанавливает граничные условия, идентичные тому, как np.quantile устанавливает его: p_k = (k-1) / (n-1) , где n - размер выборки, а k = 1 обозначает наименьшее значение, а k = n наибольшее. Это означает, что наименьшее значение в отсортированном массиве закрепляется с квантилем = 0, а наибольшее - с квантилем = 1.

Также, как упоминалось в предыдущем посте, вы можете воспроизвести 3 примера из Википедии с типом 1:

> quantile(c(15, 20, 35, 40, 50), probs=c(0.05, 0.3, 0.4, 0.5, 1), type=1)
  5%  30%  40%  50% 100% 
  15   20   20   35   50 
> quantile(c(3, 6, 7, 8, 8, 10, 13, 15, 16, 20), probs=c(0.25, 0.5, 0.75, 1), type=1)
 25%  50%  75% 100% 
   7    8   15   20 
> quantile(c(3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20), probs=c(0.25, 0.5, 0.75, 1), type=1)
 25%  50%  75% 100% 
   7    9   15   20 

Это вызывает несколько интересных вопросов:

1.) должен ли параметр np.quantile по умолчанию отслеживать значение по умолчанию R.quantile?
2.) должен ли np.quantile переключиться на алгоритм типа 1?

Поскольку даже сама Википедия согласна с тем, что стандартного определения процентиля не существует, я думаю, что пока алгоритм работает и пользователь знает, как он работает, ни (1), ни (2) не имеют большого значения. Я больше поддерживаю (1), потому что Python и R - две из самых популярных платформ для анализа данных, и было бы неплохо, если бы они могли проверять друг друга. Учитывая это, я думаю, что (2) не нужен.

Да, и R, и Numpy по умолчанию используют метод 7, и он должен оставаться таким. Вопрос в том, добавлять или нет другие методы.

Если кто - то интерес, я помещал независимый модуль с 9 процентильных методами, здесь . Не стесняйтесь использовать его или адаптироваться к Numpy, если знаете, как.

Спасибо @ ricardoV94 .

Итак, просто ради удовольствия, я провел опрос пользователей R. Из 20 человек, которые ответили, 20 используют только метод по умолчанию в quantile . Они варьируются от магистров общественного здравоохранения до докторов наук в области статистики.

Лично я не уверен, стоит ли использовать numpy для поддержки 9 различных способов вычисления квантилей. Я думаю, что большинство пользователей просто будут использовать значение по умолчанию.

Как бы то ни было, есть функция scipy.stats.mstats.mquantiles, которая поддерживает 6 из 9 методов (непрерывные), и в документе очень явно указаны ссылки на реализацию R.

@albertcthomas а, это полезно знать. Хотя, я думаю, что в идеале мы бы немного скрыли эту сложность в numpy. И нам в основном нужно исправить несмежные версии IIRC. Потому что они в основном не дают наиболее распространенных методов.

Да, действительно, numpy не обязательно должен поддерживать эти методы, если они реализованы в модуле scipy stats.

Лично я был бы сторонником метода вычисления квантиля на основе обобщенной обратной функции кумулятивной функции распределения. Тот факт, что такой метод недоступен, привел меня к этой проблеме :).

@albertcthomas, если у вас есть какие-либо намеки / знания об этом, сообщите об этом! Мы немного застряли из-за отсутствия ясности, что на самом деле является хорошим значением по умолчанию. И я считаю, что это довольно неприятная проблема.

Самое главное, нам нужно несколько хороших настроек по умолчанию. А это, вероятно, означает реализацию 2-3 методов (полностью переделывая несмежные). Я согласен с поддержкой более или менее сложных вещей, но мне бы хотелось, чтобы мы выбрали несколько «типичных / хороших».

Я бы сказал, что линейного метода (текущее значение по умолчанию) и обратной функции кумулятивного распределения (которую я искал, когда я создавал этот выпуск, а также @albertcthomas, если я правильно понимаю) будет достаточно. По сути, это позволяет выбрать, нужна им интерполяция или нет.

И другие реализуемые в настоящее время альтернативы обязательно должны быть удалены.

Обязательно следует добавить обратную кумулятивную функцию распределения. Это один из самых популярных методов оценки квантиля из данной выборки наблюдений в статистике.

И другие реализуемые в настоящее время альтернативы обязательно должны быть удалены.

@ ricardoV94 , вы говорите это, потому что ни одна из альтернатив не упоминается ни в Википедии, ни в статье Гайндмана и Фана?

Да, афаик они не реализованы ни в каком другом пакете.

Я не понимаю, почему кто-то захочет использовать эти методы, и их имена
также потенциально вводит в заблуждение.

Альберт Томас [email protected] escreveu no dia quarta, 2.01.2019
à (s) 14:18:

И другие альтернативы, реализованные в настоящее время, обязательно должны быть
удалено.

@ ricardoV94 https://github.com/ricardoV94 вы говорите это, потому что
ни одна из альтернатив не упоминается ни в Википедии, ни в Hyndman и
Бумага фаната?

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/numpy/numpy/issues/10736#issuecomment-450861068 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AbpAmfUoJNk3YHOSHNeVN03Va5wtvkHQks5u_LGugaJpZM4SnVpE
.

Благодаря! Почему бы не открыть PR, чтобы добавить обратное кумулятивное распределение в качестве метода, доступного в np.percentile? оставляя этот вопрос открытым, если мы хотим продолжить обсуждение альтернатив (кроме текущего значения по умолчанию, которое должно оставаться по умолчанию). Как в numpy обрабатывается устаревание?

Дополнительная информация здесь - Python 3.8 добавил statistics.quantiles - мы должны рассмотреть возможность добавления эквивалентного режима в np.quantile

Путь вперед здесь, вероятно, состоит в том, чтобы добавить method kwarg, отражающий statistics one, и, возможно, добавить еще 0-2 (в этом случае было бы хорошо проверить исходных авторов на python) .

Я не уверен, совпадают ли значения по умолчанию между нашими и их, было бы жаль, если бы они этого не сделали, но это все еще кажется лучшей идеей (и в значительной степени то, что мы имели в виду в любом случае). 0–2 новых "метода" тоже можно добавить. В этом случае было бы хорошо пинговать людей статистики python на настоящие имена ...

PR очень приветствуются, я бы хотел, чтобы это продвинулось вперед, но я не буду делать этого в ближайшем будущем.

@ eric-wieser Я обращаю внимание на то, что у вас есть пара связанных PR, занимается ли кто-нибудь из них?

Я собираюсь отодвинуть это до 1.19, чтобы это не блокировало. Но это не значит, что это нельзя исправить в 1.18 :)

@charris : Какие пиары вы имеете в виду?

Я, к сожалению, не думаю, что есть что-то в этом направлении.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги