Pergunta

Eu estou usando C ++ para escrever um script de raiz para alguma tarefa. Em algum momento eu tenho uma matriz de duplas em que muitos são bastante semelhantes e um ou dois são diferentes. Quero média Todos os número exceto aqueles polegares doloridos. Como devo abordá-lo? Por exemplo, vamos considerar:

x = [2.3, 2.4, 2.11, 10.5, 1.9, 2.2, 11.2, 2.1]

Eu quero de alguma forma média Todos os números, exceto 10.5 e 11.2, os diferentes. Este algoritmo vai repetidos milhares de vezes ea matriz de duplas tem 2000 entradas, de modo optimization (mantendo a legibilidade) é desejada. Graças SO!

Confira: http://tinypic.com/r/111p0ya/3 Os números "dissimilares" dos valores de y do pulso.

O ponto deste para determinar o valor terreno para a forma de onda. Eu estou comparando o valor mais negativo para o chão e esperava conseguir um método melhor para o aterramento do que a média dos primeiros N pontos na amostra.

Foi útil?

Solução

Uma vez que você estiver usando ROOT que você pode considerar a olhar para as classes TSpectrum que têm suporte para extrair fundos de debaixo de um número indeterminado de picos ...

Eu nunca usei-los com tanto barulho da linha de base, mas eles devem ser robustos.

BTW: o que é a fonte de dados. Os olhares de pico, como um pulso detector de partículas, mas o alto nível de jitter fundo sugere que você poderia realmente melhorar as coisas por alguns ajustes relativamente menores no hardware DAQ, que pode ser melhor do que tentar resolver um problema de software difícil.

Por fim, a menos que você está restrito a algum hardware muito primitiva (caso em que como e por que você está correndo ROOT?), Se você tiver apenas um par mil tais espectros você pode pagar um algoritmo bastante lento. Ou é que 2.000 espectros por evento e uma taxa de eventos elevada?

Outras dicas

Se você puder, manter uma lista ordenada; então você pode facilmente cortar a cabeça ea cauda da lista cada vez que você calcular a média.

Este é muito parecido com a remoção de outliers com base na mediana (ou seja, você vai precisar de duas passagens sobre os dados, um para encontrar a mediana - que é quase tão lento como triagem para dados de ponto flutuante, o outro para calcular a média), mas requer menos sobrecarga no momento da elaboração da média no custo de manutenção de uma lista ordenada. Qual deles é mais rápida dependerá inteiramente de suas circunstâncias. Pode ser, é claro, que o que você realmente quer é o de qualquer maneira mediano!

Se você tivesse dados discretos (digamos, bytes = 256 valores possíveis), você poderia usar 256 histograma 'caixas' com uma única passagem sobre seus dados colocando contando os valores que vão em cada bin, então é realmente fácil de encontrar o médio / aproximar os valores atípicos média / remover, etc. Esta seria a minha opção preferida, se você pudesse dar ao luxo de perder um pouco da precisão em seus dados, seguido por manter uma lista ordenada, se isso é apropriado para seus dados.

Uma maneira rápida poderia ser a de tomar a mediana, e em seguida, tomar as médias de número não tão longe da mediana.

"Não tão longe", sendo dependente do seu projeto.

Uma boa regra de ouro para a determinação de outliers prováveis ??é calcular o intervalo interquartil (IQR) e quaisquer valores que são 1.5 * IQR longe da mais próxima quartil são valores atípicos.

Este é o método básico muitos sistemas de estatísticas (como R) usam para detectar automaticamente os outliers.

Qualquer método que é estatisticamente significativa e uma boa maneira de abordá-lo (escuro Eru, Daniel White) vai ser muito computacionalmente intensa para repetir, e eu acho que eu encontrei uma solução que vai permitir a correção posterior (ou seja, licença it-un aterrada).

Obrigado pelas sugestões. Vou olhar para eles se eu tiver tempo e quiser ver se o seu ganho vale a desaceleração.

Aqui está um método rápido e sujo que eu usei antes (funciona bem se há muito poucos valores discrepantes no início, e você não tem condições muito complicadas para o que constitui um outlier)

O algoritmo é O (N). A única parte realmente caro é a divisão.

A verdadeira vantagem aqui é que você pode tê-lo instalado e funcionando em alguns minutos.

avgX = Array[0]  // initialize array with the first point
N = length(Array)
percentDeviation = 0.3  // percent deviation acceptable for non-outliers
count = 1
foreach x in Array[1..N-1]
    if      x < avgX + avgX*percentDeviation
       and  x > avgX - avgX*percentDeviation
          count++
          sumX =+ x
          avgX = sumX / count
    endif
endfor

return avgX
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top