Numpy: Reestruturar métodos de percentil

Criado em 12 mar. 2018  ·  53Comentários  ·  Fonte: numpy/numpy

Conforme exemplificado na página da Wikipedia: https://en.wikipedia.org/wiki/Percentile#The_nearest -rank_method

00 - Bug 01 - Enhancement high

Todos 53 comentários

Eu acho que isso já existe? Usando o exemplo da Wikipedia:

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

Isso não. Veja o exemplo 2 na página da wikipedia:

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

Quando deveria ser [7,8,15,20]

Ele também falha no terceiro exemplo

Mais próximo parece muito com "mais próximo"? Embora haja sempre outro ponto sobre como exatamente os limites funcionam.
EDIT: Ou seja, onde exatamente 0 e 100 são considerados, no ponto de dados ou antes do ponto de dados? (isso é IIRC, de qualquer maneira, existem muitas complexidades irritantes aqui)

não quero ler, acho que a diferença pode ser o parâmetro C mais abaixo, então se alguém que sabe disso quiser adicionar isso ....

Francamente, acho que adicionar o parâmetro C provavelmente seria muito bom. Mas, principalmente, uma documentação melhor seria boa, e alguém que realmente conheça essas coisas é necessário ....

Não sei se isso tem a ver com o parâmetro C, embora concorde que a opção de escolhê-lo pode ser desejável.

Eu encontrei outro tópico que acidentalmente trouxe à tona esse problema (dezembro de 2016). Parece que o algoritmo que estou procurando (e que a wikipedia chama de rank mais próximo) é mencionado neste artigo comumente citado por Hyndman-Fan (H&F) como sendo a definição de percentil mais antiga e mais estudada (foi a que aprendi em Curso de estatísticas). É uma função descontínua, então acho que o parâmetro C não se aplica aqui (posso estar errado).

Aqui está como ficaria em comparação com as outras opções fornecidas por numpy que intuitivamente parecem computar algo semelhante (ou seja, 'inferior', 'mais próximo'):

percentiles

Para mim, parece exatamente como o parâmetro C à primeira vista, a curva mais próxima é mais esticada do que a curva H&F, o que é esperado uma vez que numpy usa 1 e aparentemente H&F usa 0.

Se você quiser uma prova. Repita a coisa toda com os mesmos valores repetidos 1000 vezes, meu palpite é que eles convergirão.
EDITAR: Ou talvez não, não tenha paciência ou tempo para realmente pensar sobre isso. Mas eu ainda acho que é o parâmetro C que a wikipedia menciona, então, por favor, me prova que estou errado :)

Um gráfico como esse seria um ótimo complemento para os documentos percentuais

editar: de preferência um mostrando a abertura / fechamento das descontinuidades

Nota aos leitores: para manter este tópico gerenciável, marquei todas as discussões abaixo sobre como adicionar este gráfico aos documentos como "resolvido". O gráfico agora está na parte inferior de https://numpy.org/devdocs/reference/generated/numpy.percentile.html.

@ eric-wieser Não me importo de fazer esse gráfico. Voltarei com algo mais tarde hoje, devo postar aqui?

@seberg Vou ser honesto aqui, não sei como a interpolação está sendo calculada com base no parâmetro C. O que me faz pensar que não está relacionado é que o parâmetro C é discutido apenas na seção de interpolação linear (Wikipedia), e tanto o artigo da Wikipedia como Hyndmand & Fan discutem o algoritmo que solicitei em seções separadas das de interpolação.

Não sei se existe algum parâmetro de interpolação que sempre dê os mesmos resultados que o algoritmo que estou interessado.

Mesmo se houver, deve ser esse o caminho usado para chegar a ele? Alterar um parâmetro 'estranho' para obter a definição mais comum de percentil não parece a melhor maneira de implementá-lo imediatamente.

@ ricardoV94 , talvez, mas você não pode simplesmente mudar os padrões, por pior que sejam. Poderíamos expor algo como method = "H&K" para substituir os dois parâmetros de uma vez.

Os parâmetros C são onde você define 0% e 100% para estar em relação aos pontos de dados (no ponto de dados ou não, etc.). Como parâmetro C na wikipedia, pode muito bem ser apenas para interpolação, mas o mesmo problema causa a diferença aqui tenho certeza. C é duvidoso, claro, um nome próprio pode ser algo como range = 'min-max' ou range = 'extrapolado' ou provavelmente algo completamente diferente. Como eu disse, refaça os gráficos com muitos muitos pontos de dados (possivelmente com um ruído mínimo), e acho que você os verá convergir, já que a definição do intervalo se torna menos óbvia.

@seberg Estou bem com method = "H&K" ou talvez method = "classic". Interpolação = "nenhum" também pode fazer sentido.

Não tenho certeza de qual é o mecanismo para incluir imagens nos documentos, ou se há algum precedente para fazê-lo.

Eu sei que você pode executar o código matplotlib dentro dos documentos, que é como fazemos em outros lugares - o que também garante que ele permaneça sincronizado com a realidade.

Ok, vou pensar na melhor imagem de código nesse caso.

A parte mais problemática são os marcadores abertos e fechados para descontinuidade, uma vez que matplotlib não tem uma função embutida para isso (afaik). Codificá-los não faria muito sentido nesse caso.

Talvez pule aqueles por agora. Seria bom se matplotlib tivesse algum suporte automático para eles.

Espero que alguém tenha uma sugestão melhor, que ainda seja elegante em relação à descontinuidade.

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

Eu acho que interpolation = 'linear' deveria ser uma linha regular não escalonada, mas por outro lado tem uma boa aparência. Você pode fazer um PR adicionando isso aos documentos?

Na verdade, step está causando artefatos enganosos em geral, então estou inclinado a evitá-lo. linspace(0, 100, 60) também produziria coordenadas intermediárias mais precisas

Não tenho ideia de como fazer um PR.

Sinta-se à vontade para fazer isso com sua conta, adicionando ou discutindo as alterações sugeridas.

Eu acho que você pode mudar C com algo assim (teste em algo). Chame a função em seus percentis e, em seguida, conecte-a à versão numpy (que usa C = 1, que é autônomo, exceto pela correção de percentis fora do limite agora):

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

E pronto, com "mais próximo" você obterá seu "H&F" e com linear você obterá o gráfico da Wikipedia. (enquanto eu entendi algo errado, mas tenho quase certeza de que entendi certo).

Como eu disse, a diferença é onde você coloca os pontos de dados de 0-100 (uniformemente) em relação ao último ponto. Para C = 1, você coloca min (dados) no percentil 0 etc. Não tenho ideia sobre "o que faz mais sentido", provavelmente importa um pouco do ponto de vista geral. O nome inclusivo para 1 e exclusivo para 0 faz algum sentido, eu acho (quando você pensa sobre o intervalo total de percentis, já que o intervalo possível exclusivo está fora do intervalo de dados). C = 1/2 também é exclusivo nesse sentido.

Eu gostaria de adicionar o parâmetro C, mas gostaria que alguém sugerisse um nome descritivo, se possível. Eu também não me importaria com algo como um "método" ou algo assim para tornar os melhores padrões óbvios (combinação de interpolação + C). Ou você basicamente decidimos que a maioria das combinações nunca é usada e não é útil, tudo bem ...

No final, meu problema é: eu quero que um estatístico me diga quais métodos têm consenso (R tem algumas coisas, mas a última vez que alguém veio por aqui era apenas uma cópia do R doc ou semelhante, sem defini-lo em um contexto numpy em tudo, desnecessário dizer, era inútil para o público em geral, citar artigos teria sido mais útil).

Não quero ler aquele artigo de H&F (honestamente, também não parece muito bom de se ler), mas acho que você também poderia vê-lo de um ponto de vista de apoio. A versão numpy "mais próximo" (ou qualquer outra) não tem suporte idêntico (nos percentis) para cada ponto de dados, H&F tem suporte igual para "mais próximo" e talvez para o ponto médio seria C = 1/2, não tenho certeza.
Eu continuo me repetindo, não sei se esse argumento de suporte (contra C = 1, como numpy o usa), é realmente um motivo real.

EDIT: o ponto médio tem suporte igual (para a área entre os pontos de dados, não para o ponto em si) em numpy, então com "C = 1"

@seberg Não parece funcionar comigo. Você pode postar seu código mostrando que está funcionando?

Bem, eu entendi errado o sinal, naquele código lá em cima, então era o oposto (C = 0 a sem operação não 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 Fechar, mas ainda não. Para a = [0,1,2,3] e percentiles = [25, 50, 75, 100] , np.percentile (a, scale_percentiles(percentiles, len(a), C=0), interpolation='nearest) retorna [0, 2, 3, 3] , quando deveria retornar [0,1,2,3] .

Tive que fazer os percentis da lista dtype=np.float ou sua função daria um erro, mas não acho que seja esse o problema.

A função do método clássico é simples:
Percentil / 100 * N -> Se for um número inteiro que é o índice, se não, use o teto como índice.

Apesar disso, o argumento C parece estar funcionando conforme o esperado, então pode ser implementado se as pessoas quiserem usá-lo para a interpolação. Eu ainda gostaria de um método = 'clássico' ou interpolação = 'nenhum' que funcionasse como o da Wikipédia.

Para depuração, esta é minha implementação feia e não entorpecida do método clássico:

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)]

e um mais numpythônico:

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

Essas diferenças soam como questões de ponto flutuante / arredondamento (que você
pareço ciente), e talvez meu palpite com C = 0 esteja errado e você deseja
C = 0,5.
Meu objetivo era dizer de onde vem a diferença (O "parâmetro C"
IMO, embora haja provavelmente boas razões para não gostar de muitos
combinações). Não era para dar a você / implementar uma solução alternativa.

Quanto ao método "clássico", francamente não me importo muito com o que
deve ser. Pelo que eu sei, clássico significa apenas "alguns
as pessoas usam ".

Em termos de solução, minha primeira impressão é que "clássico" ou qualquer outra
nome, apenas adiciona outra opção confusa com um nome pouco claro. eu espero
que esta discussão pode ir no sentido de realmente tornar todos
boas opções (comuns) disponíveis para os usuários de uma forma limpa e transparente
caminho. Melhor de uma forma que as pessoas possam realmente entender.

Podemos adicionar mais um método, mas, francamente, só gosto pela metade. Quando nós
mais métodos adicionados pela última vez (não me lembro o que mudou exatamente)
já atrasou e esperava que alguém pulasse e descobrisse
o que devemos ter. Desnecessário dizer que nunca realmente aconteceu. E agora
Estou tentando apontar as diferenças e tentar ver como isso pode se encaixar
com o que temos atualmente.

Então, minha impressão é (com possíveis problemas com arredondamento e exatidão
correspondências de percentil), temos (provavelmente muitas) opções de "interpolação"
e exigiria o "parâmetro C" ou o que você quiser chamá-lo
ser capaz de fazer quase tudo.
E eu ficaria muito feliz se alguém pudesse me dizer como todos os
(comum) "Métodos" lá fora se enquadram nessas categorias, parece que
mais do que C = 0,0.5,1 existem mesmo, e talvez alguns até mesmo fora daqueles
opções ....

Talvez eu esteja indo pela pista errada, mas adicionando "Método1" com um
nome obscuro que realmente não diz a ninguém em que difere do
outros métodos não parecem úteis para mim (exceto para alguém que
acontece de já saber o nome "Método1" e está procurando por ele. E
por favor, não diga que o "clássico" é o mais óbvio, há
muita variação nas implementações por aí.

Outra forma pode ser descontinuar a "interpolação", mas ter uma lista
de métodos também é muito menos agradável do que sugerir "interpolação linear"
para dizer que não é um comportamento de degrau, etc .... E se formos assim,
Ainda quero uma visão geral razoável.

Você não precisa fazer isso, mas se quisermos adicionar um novo método, precisamos de um
forma de adicionar que não confunde ainda mais a todos e é claro!

Deixe-me resumir então:

1) No momento, o numpy oferece apenas um método útil: interpolação = 'linear', e os outros são apenas pequenas variações em torno dele que não parecem ser realmente usadas por ninguém. Outros pacotes têm muitas opções mais relevantes.

2) Adicionar os outros valores para C = 0 ou C = 0,5 faz sentido para mim. Todos os métodos de interpolação podem funcionar em combinação com eles, embora, novamente, eles provavelmente nunca serão usados.

3) Se um dos combos entre métodos de interpolação e argumento C consegue replicar o método clássico (a referência e a wikipedia e minha experiência pessoal concordam que é o método mais comumente ensinado), então estou feliz com isso. Pode-se afirmar nos documentos que tal combinação produz o método clássico de não interpolação. Não tenho certeza se é apenas devido a problemas de precisão da flutuação, mas agradeço seu esforço em lidar com isso de uma forma mais integrada!

4) Se nenhum dos combos atingir o mesmo resultado, então acho que um método diferente faria sentido. Possivelmente chamado de interpolação = 'nenhum' seria menos confuso.

Resumindo: as opções atuais de numpy.percentile parecem um tanto confusas e limitadas. O documento mencionado acima oferece uma boa visão geral de outros métodos úteis. Junto com a página da Wikipedia, eles poderiam funcionar como um ponto de partida para o design de um conjunto de opções mais exaustivo e útil para numpy.percentile. Esperançosamente, alguém gostaria de trabalhar nesta tarefa.

O atual "mais próximo" faz sentido em alguns / quaisquer casos? Se o método de espaçamento ("C") ou qualquer outro faz uma diferença tão grande para interpolação linear / coisas fracionárias, talvez eu só esteja surpreso que ninguém tenha feito isso para aproximações não fracionárias ?! O suporte constante é tão importante e há uma razão para descartar o argumento inverso do CDF para os métodos de interpolação?

Combos são inúteis a menos que sejam compreensíveis e os comumente usados ​​fáceis de encontrar, então eu duvido. Para interpolação, muitas opções parecem existir (por exemplo, http://mathworld.wolfram.com/Quantile.html Q4 a Q9, acho que a documentação R é praticamente idêntica, mas acho que provavelmente não está completa, por exemplo, matlab ...) embora Eu não tenho ideia se eles realmente fazem sentido;).

A questão é que a "interpolação" aponta o que fazer entre pontos definidos exatamente, mas há muitas (estranhamente muitas) maneiras de colocar esses pontos, pelo menos ao usar a "interpolação linear", então parece uma abordagem ruim adicionar a isso. Você queria um "rank mais próximo" que soasse muito (e esteja no espírito) interpolação = "mais próximo", mas a escolha da "posição de plotagem" exata parece "fora do padrão", então será impossível adivinhar e, portanto, uma má escolha.

Então eu preferiria até mesmo depreciar agressivamente tudo (exceto provavelmente linear).

Mas, se desaprovarmos, quero fazer isso 100% certo, e isso pode exigir um pouco mais de clareza sobre o que existe, o que deveria existir e o que definitivamente não deveria existir.

eu concordo totalmente com você

@ ricardoV94 : você tem alguma opinião sobre as definições de linear para o caso de quantil ponderado proposto em # 9211? Existem alguns gráficos no mesmo estilo.

Talvez o @ ricardoV94 possa comentar sobre isso (seria legal), mas acho que a questão é bem ortogonal. Os pesos são provavelmente apenas pesos de tipo de frequência, supondo que não haja outros pesos razoavelmente definidos para percentil (não vejo como), não deve haver qualquer ambigüidade ao implementá-los, mas não sei ao certo.

Você também pode tentar pingar josef-pkt nesse PR e esperar que ele tenha um comentário rápido se ele acha que é uma boa ideia / certo.

Se alguém quiser assumir daqui, escrevi uma função não otimizada que calcula o
Métodos de estimativa de 9 percentis / quantis descritos por Hyndman e Fan (1996) e também usados ​​em R.

O método 1 corresponde ao 'método clássico de classificação mais próxima', conforme discutido na Wikipedia . O método 7 é equivalente à implementação atual do Numpy (interpolação = 'linear'). Os métodos restantes de interpolação Numpy não estão incluídos (e não parecem ser úteis de qualquer maneira).

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_]

Os métodos contínuos também podem ser implementados de forma mais eficiente assim.

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)

Alguém quer assumir daqui? Não estou qualificado para isso.

Como mencionado no post anterior, parece que a implementação padrão atual de quantil de numpy corresponde a R .

Em 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 

Em 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. ])

que obviamente não reproduzem os exemplos dados na Wikipedia:
https://en.wikipedia.org/wiki/Percentile

Na verdade, se você acessar a página de ajuda do R para quantile https://www.rdocumentation.org/packages/stats/versions/3.5.0/topics/quantile
você veria que o método padrão R (Tipo 7) define as condições de contorno idênticas a como np.quantile define: p_k = (k-1) / (n-1) , onde n é o tamanho da amostra e k = 1 denota o menor valor, enquanto k = n é o maior. Isso significa que o menor valor na matriz classificada é fixado em quantil = 0, e o maior é fixado em quantil = 1.

Também conforme mencionado na postagem anterior, você pode reproduzir os 3 exemplos na Wikipedia com Tipo 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 

Isso levanta algumas questões interessantes:

1.) o padrão de np.quantile deve rastrear o padrão de R.quantile?
2.) np.quantile deve mudar para o algoritmo Tipo 1?

Visto que até a própria Wikipedia concorda que não existe uma definição padrão de percentil, acho que, desde que o algoritmo seja sólido e o usuário esteja ciente de como ele funciona, nem (1) nem (2) importa tanto. Sou mais a favor de (1) porque Python e R são duas das plataformas de análise de dados mais populares por aí, e seria bom se eles pudessem examinar um ao outro. Dado isso, acho que (2) é desnecessário.

Sim, tanto R quanto Numpy assumem o método 7 e deve ser mantido assim. A questão é adicionar ou não os outros métodos.

Se alguém estiver interessado, coloco um módulo independente com os métodos do 9º percentil, aqui . Sinta-se à vontade para usá-lo ou adaptar-se ao Numpy se souber como.

Obrigado @ ricardoV94 .

Então, só por diversão, fiz uma enquete no trabalho com os usuários R. Das 20 pessoas que responderam, 20 usam apenas o método padrão em quantile . Eles variam de estudantes de mestrado em saúde pública a pesquisadores de doutorado em estatística.

Pessoalmente, não tenho certeza se vale a pena o esforço para o numpy suportar 9 maneiras diferentes de calcular quantis. Acho que a maioria dos usuários usará apenas o padrão.

Para o que vale a pena, existe a função scipy.stats.mstats.mquantiles que suporta 6 dos 9 métodos (os contínuos) e o documento declara muito explicitamente os links com a implementação de R.

@albertcthomas ah, é bom saber. Embora, eu acho que idealmente esconderíamos essa complexidade um pouco entorpecida. E principalmente precisamos consertar as versões não contíguas do IIRC. Porque esses basicamente não fornecem os métodos mais comuns.

Sim, numpy pode não necessariamente ter que suportar esses métodos se eles forem implementados no módulo scipy stats.

Pessoalmente, eu seria a favor de um método que calcule o quantil a partir do inverso generalizado da função de distribuição cumulativa. O fato de que tal método não está disponível me leva a este problema :).

@albertcthomas se você tiver alguma dica / conhecimento sobre isso, diga! Estamos um pouco presos devido à falta de clareza sobre o que é realmente um bom padrão. E eu acho que é um problema muito chato.

Mais importante ainda, precisamos de alguns bons padrões. E isso provavelmente significa implementar 2-3 métodos (reformular completamente os não contíguos). Estou bem em apoiar coisas mais ou mais complexas, mas adoraria se pudéssemos decidir sobre algumas "típicas / boas".

Eu diria que o método linear (padrão atual) e o inverso da função de distribuição cumulativa (que eu estava procurando quando criei este problema, bem como @albertcthomas se bem entendi) seriam suficientes. Basicamente, permite escolher se deseja interpolação ou não.

E as outras alternativas atualmente implementadas devem ser definitivamente removidas.

O inverso da função de distribuição cumulativa deve definitivamente ser adicionado. É um dos estimadores mais populares de um quantil de uma determinada amostra de observações em estatísticas.

E as outras alternativas atualmente implementadas devem ser definitivamente removidas.

@ ricardoV94 você está dizendo isso porque nenhuma das alternativas é referenciada na Wikipedia nem no artigo de Hyndman e Fan?

Sim, afaik eles não estão implementados em nenhum outro pacote.

Não vejo por que alguém iria querer usar esses métodos, e seus nomes são
também potencialmente enganoso.

Albert Thomas [email protected] escreveu no dia quarta, 01/02/2019
à (s) 14:18:

E as outras alternativas atualmente implementadas devem ser definitivamente
removido.

@ ricardoV94 https://github.com/ricardoV94 você está dizendo isso porque
nenhuma das alternativas são referenciadas na Wikipedia nem no Hyndman e
Jornal de Fan?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/numpy/numpy/issues/10736#issuecomment-450861068 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AbpAmfUoJNk3YHOSHNeVN03Va5wtvkHQks5u_LGugaJpZM4SnVpE
.

Obrigado! Por que não abrir um PR para adicionar o inverso da distribuição cumulativa como um método disponível em np.percentil? enquanto mantemos esta questão aberta se quisermos continuar discutindo sobre alternativas (exceto o padrão atual que deve permanecer o padrão). Como a suspensão de uso é tratada no numpy?

Mais algumas informações aqui - Python 3.8 adicionou statistics.quantiles - devemos olhar para adicionar um modo equivalente a np.quantile

O caminho a seguir aqui é provavelmente adicionar um method kwarg espelhando o statistics one, e possível adicionar mais 0-2 (nesse caso, seria bom fazer ping dos autores originais no python) .

Não tenho certeza se os padrões correspondem entre os nossos e os deles, o que seria uma vergonha se não o fizessem, mas ainda parece ser a melhor ideia (e praticamente o que tínhamos em mente, de qualquer maneira). 0-2 novos "métodos" seriam adequados para adicionar também. Nesse caso, seria bom fazer ping para o pessoal de estatísticas do python sobre os nomes reais ...

RPs, muito bem-vindos, gostaria que isso avançasse, mas não o farei no futuro imediato.

@ eric-wieser Noto que você tem alguns RPs pendentes. Algum deles lida com isso?

Vou empurrar para 1,19 para que não seja um bloqueador. Mas isso não significa que não possa ser corrigido para 1.18 :)

@charris : Quais

Não creio que haja nenhum nessa direção ainda, infelizmente.

Esta página foi útil?
0 / 5 - 0 avaliações