Eu tenho uma série de listas de números, por exemplo:
[0] (0.01, 0.01, 0.02, 0.04, 0.03)
[1] (0.00, 0.02, 0.02, 0.03, 0.02)
[2] (0.01, 0.02, 0.02, 0.03, 0.02)
...
[n] (0.01, 0.00, 0.01, 0.05, 0.03)
O que eu gostaria de fazer é calcular com eficiência a média e o desvio padrão em cada índice de uma lista, em todos os elementos da matriz.
Para fazer a média, estive percorrendo a matriz e somando o valor em um determinado índice de uma lista. No final, divido cada valor em minha "lista de médias" por n
(estou trabalhando com uma população, não uma amostra da população).
Para fazer o desvio padrão, faço um loop novamente, agora que calculei a média.
Eu gostaria de evitar percorrer a matriz duas vezes, uma para a média e outra para o SD (depois de ter uma média).
Existe um método eficiente para calcular os dois valores, passando pelo array apenas uma vez? Qualquer código em uma linguagem interpretada (por exemplo, Perl ou Python) ou pseudocódigo está bem.
fonte
Respostas:
A resposta é usar o algoritmo de Welford, que é muito claramente definido após os "métodos ingênuos" em:
É mais estável numericamente do que os coletores de soma de quadrados simples de duas passagens ou online sugeridos em outras respostas. A estabilidade só importa realmente quando você tem muitos valores próximos uns dos outros, pois eles levam ao que é conhecido como " cancelamento catastrófico " na literatura de ponto flutuante.
Você também pode querer melhorar a diferença entre dividir pelo número de amostras (N) e N-1 no cálculo de variância (desvio ao quadrado). A divisão por N-1 leva a uma estimativa imparcial da variância da amostra, enquanto a divisão por N na média subestima a variância (porque não leva em consideração a variância entre a média da amostra e a média verdadeira).
Escrevi duas entradas de blog sobre o tópico que fornecem mais detalhes, incluindo como excluir valores anteriores online:
Você também pode dar uma olhada no meu implemento Java; o javadoc, o código-fonte e os testes de unidade estão todos online:
stats.OnlineNormalEstimator
stats.OnlineNormalEstimator.java
test.unit.stats.OnlineNormalEstimatorTest.java
fonte
A resposta básica é acumular a soma de x (chame de 'soma_x1') e x 2 (chame de 'soma_x2') conforme você avança. O valor do desvio padrão é então:
Onde
Este é o desvio padrão da amostra; você obtém o desvio padrão da população usando 'n' em vez de 'n - 1' como divisor.
Você pode precisar se preocupar com a estabilidade numérica de tirar a diferença entre dois números grandes se estiver lidando com amostras grandes. Vá para as referências externas em outras respostas (Wikipedia, etc) para obter mais informações.
fonte
int
em C para armazenar a soma dos quadrados, terá problemas de estouro com os valores listados.Aqui está uma tradução literal pura do Python da implementação do algoritmo de Welford de http://www.johndcook.com/standard_deviation.html :
https://github.com/liyanage/python-modules/blob/master/running_stats.py
Uso:
fonte
Talvez não seja o que você estava pedindo, mas ... Se você usar uma matriz numpy, ela fará o trabalho para você, de forma eficiente:
A propósito, há uma discussão interessante nesta postagem do blog e comentários sobre métodos de uma passagem para meios de computação e variações:
fonte
O módulo runstats do Python serve exatamente para esse tipo de coisa. Instale runstats do PyPI:
Os resumos de runstats podem produzir a média, a variação, o desvio padrão, a assimetria e a curtose em uma única passagem de dados. Podemos usar isso para criar sua versão "em execução".
Os resumos de estatísticas são baseados no método de Knuth e Welford para calcular o desvio padrão em uma passagem, conforme descrito em Art of Computer Programming, Vol 2, p. 232, 3ª edição. O benefício disso são resultados numericamente estáveis e precisos.
Isenção de responsabilidade: eu sou o autor do módulo runstats do Python.
fonte
Statistics
um.pop
método para que as estatísticas de rolagem também pudessem ser calculadas.runstats
não mantém uma lista interna de valores, então não tenho certeza se isso é possível. Mas as solicitações de pull são bem-vindas.Statistics :: Descriptive é um módulo Perl muito decente para estes tipos de cálculos:
Resultado:
fonte
Dê uma olhada no PDL (pronuncia-se "piddle!").
Esta é a linguagem de dados Perl projetada para matemática de alta precisão e computação científica.
Aqui está um exemplo usando suas figuras ....
Que produz:
Dê uma olhada em PDL :: Primitive para obter mais informações sobre o statsover função . Isso parece sugerir que ADEV é o "desvio padrão".
No entanto, pode ser PRMS (que mostra o exemplo de Estatísticas :: Descritivo de Sinan) ou RMS (que mostra o exemplo de NumPy de ars). Acho que um desses três deve estar certo ;-)
Para obter mais informações sobre o PDL, dê uma olhada em:
fonte
Qual é o tamanho do seu array? A menos que tenha zilhões de elementos, não se preocupe em percorrê-lo duas vezes. O código é simples e facilmente testado.
Minha preferência seria usar a extensão matemática numpy array para converter seu array de arrays em um array 2D numpy e obter o desvio padrão diretamente:
Se isso não for uma opção e você precisar de uma solução Python pura, continue lendo ...
Se o seu array é
Então, o desvio padrão é:
Se você estiver determinado a percorrer sua matriz apenas uma vez, as somas corridas podem ser combinadas.
Isso não é tão elegante quanto a solução de compreensão de lista acima.
fonte
Você pode consultar o artigo da Wikipedia sobre Desvio Padrão , em particular a seção sobre Métodos de cálculo rápido.
Também descobri um artigo que usa Python, você deve ser capaz de usar o código dele sem muitas alterações: Mensagens subliminares - executando desvios padrão .
fonte
Acho que esse problema vai te ajudar. Desvio padrão
fonte
Aqui está um "one-liner", espalhado por várias linhas, em estilo de programação funcional:
fonte
fonte
Como descreve a seguinte resposta: O pandas / scipy / numpy fornece uma função de desvio padrão cumulativo? O módulo Python Pandas contém um método para calcular o desvio padrão em execução ou cumulativo . Para isso, você terá que converter seus dados em um dataframe do pandas (ou em uma série se for 1D), mas existem funções para isso.
fonte
Gosto de expressar a atualização desta forma:
para que uma função de passagem única se pareça com isto:
observe que isso está calculando a variância da amostra (1 / N), não a estimativa não enviesada da variância da população (que usa um fator de normalização 1 / (N-1)). Ao contrário das outras respostas, a variável,
var
que acompanha a variância em execução, não cresce em proporção ao número de amostras. Em todos os momentos, é apenas a variância do conjunto de amostras visto até agora (não há "divisão final por n" para obter a variância).Em uma aula seria assim:
Isso também funciona para amostras ponderadas:
fonte