O algoritmo P2 é uma boa descoberta. Ele funciona fazendo várias estimativas do quantil, atualizando-as periodicamente e usando interpolação quadrática (não linear, não cúbica) para estimar o quantil. Os autores afirmam que a interpolação quadrática funciona melhor nas caudas do que a interpolação linear e cúbica seria muito exigente e difícil.
Você não indica exatamente como essa abordagem falha nos dados "de cauda pesada", mas é fácil adivinhar: as estimativas de quantis extremos para distribuições de cauda pesada serão instáveis até que uma grande quantidade de dados seja coletada. Mas isso será um problema (em menor grau), mesmo que você armazene todos os dados, portanto, não espere milagres!
De qualquer forma, por que não definir marcadores auxiliares - vamos chamá-los de e nos quais você tem certeza absoluta de que o quantil estará e armazenar todos os dados que estão entre e ? Quando o seu buffer for preenchido, você precisará atualizar esses marcadores, mantendo sempre . Um algoritmo simples para fazer isso pode ser planejado a partir de uma combinação de (a) a estimativa P2 atual do quantil e (b) contagens armazenadas do número de dados menor que e do número de dados maior que . Dessa forma, você pode, com alta certeza, estimar o quantil da mesma maneira que se tivesse todo o conjunto de dados sempre disponível, mas você só precisa de um buffer relativamente pequeno.x 6 x 0 x 6 x 0 ≤ x 6 x 0 x 6x0 0x6x0 0x6x0 0≤ x6x0 0x6
Especificamente, estou propondo uma estrutura de dados para manter informações parciais sobre uma sequência de valores de dados . Aqui, é uma lista vinculadan x 1 , x 2 , … , x n y( k , y , n )nx1 1, x2, … , Xny
y =( x( N )[ k + 1 ]≤ x( N )[ k + 2 ]≤ ⋯ ≤ x( N )[ k + m ]) .
Nesta notação denota o menor dos valores lidos até agora. é uma constante, o tamanho do buffer . i th n x m yx( N )[ i ]Euºn xmy
O algoritmo começa preenchendo com os primeiros dados encontrados e colocando-os na ordem classificada, do menor para o maior. Seja o quantil a ser estimado; por exemplo, = 0,99. Ao ler existem três ações possíveis: m q q x n + 1ymqqxn + 1
Se , aumente .xn + 1< x( N )[ k + 1 ]k
Se , não faça nada.xn + 1> x( N )[ k + m ]
Caso contrário, insira em . anoxn + 1y
De qualquer forma, incremente .n
O procedimento de inserção coloca em na ordem classificada e, em seguida, elimina um dos valores extremos em : y yxn + 1yy
Se , remova de e aumente ;x ( n ) [ k + 1 ] y kk + m / 2 < n qx( N )[ k + 1 ]yk
Caso contrário, remova de . yx( N )[ k + m ]y
Desde que seja suficientemente grande, esse procedimento agrupará o verdadeiro quantil da distribuição com alta probabilidade. Em qualquer etapa pode ser estimado da forma habitual em termos de e , que provavelmente estará em . (Acredito que só precise ser dimensionado como a raiz quadrada da quantidade máxima de dados ( ), mas não realizei uma análise rigorosa para provar isso.) De qualquer forma, o algoritmo detectará se foi bem-sucedido (por comparando e a ).n x ( n ) [ ⌊ q n ⌋ ] x ( n ) [ ⌈ q n ⌉ ] y m N k / n ( k + m ) / n qmnx( N )[ ⌊ qn ⌋]x( N )[ ⌈ qn⌉]ymNk/n(k+m)/nq
Testar com até 100.000 valores, usando e (o caso mais difícil) indica que esse algoritmo tem uma taxa de sucesso de 99,5% na obtenção do valor correto de . Para um fluxo de valores, isso exigiria um buffer de apenas dois milhões (mas três ou quatro milhões seriam uma escolha melhor). O uso de uma lista duplamente vinculada classificada para o buffer requer um esforço de = ao identificar e excluir as operações máximas ou mínimas de . A inserção relativamente cara normalmente precisa ser feita apenas q=0,5x ( n ) [ ⌊ q n ⌋ ] N=10 12 O(log( √m=2N−−√q=.5x(n)[⌊qn⌋]N=1012O(log(N))O(1)O( √O(log(N−−√))O(log(N))O(1)O(N+ √O(N−−√)vezes. Portanto, os custos computacionais desse algoritmo são no tempo e no armazenamento.O( √O(N+N−−√log(N))=O(N)O(N−−√)