Question

J'utilise C ++ pour écrire un script ROOT pour une tâche. À un moment donné, j'ai un tableau de doubles dans lequel beaucoup sont assez similaires et un ou deux sont différents. Je veux faire la moyenne de tout le nombre sauf les pouces douloureux. Comment devrais-je l'aborder? Par exemple, considérons:

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

Je veux en quelque sorte faire la moyenne de tous les nombres sauf 10.5 et 11.2 , les différents. Cet algorithme va se répéter plusieurs milliers de fois et le tableau de doublons a 2000 entrées, donc une optimisation (tout en maintenant la lisibilité) est souhaitée. Merci beaucoup!

Découvrez: http://tinypic.com/r/111p0ya/3 Le " dissemblable " numéros des valeurs y de l'impulsion.

Le point de ceci pour déterminer la valeur de sol pour la forme d'onde. Je compare la valeur la plus négative au sol et espère obtenir une meilleure méthode de mise à la terre que de moyenner les N premiers points de l’échantillon.

Était-ce utile?

La solution

Étant donné que vous utilisez ROOT, vous pouvez envisager de consulter les classes TSpectrum qui prennent en charge l'extraction d'arrière-plans à partir d'un nombre non spécifié de pics ...

Je ne les ai jamais utilisés avec autant de bruit de base, mais ils devraient être robustes.

BTW: quelle est la source de ces données. Le pic ressemble à une impulsion de détecteur de particules, mais le niveau élevé d’instabilité de l’arrière-plan suggère que vous pouvez vraiment améliorer les choses en apportant des ajustements assez mineurs au matériel DAQ, ce qui peut être mieux que d’essayer de résoudre un problème logiciel difficile.

Enfin, à moins que vous ne soyez limité à un matériel très primitif (dans quel cas, pourquoi et comment exécutez-vous ROOT?), si vous n’avez que quelques milliers de spectres de ce type, vous pouvez vous permettre un algorithme plutôt lent. Ou est-ce 2000 spectres par événement et un taux élevé d'événements?

Autres conseils

Si vous le pouvez, maintenez une liste triée. alors vous pouvez facilement couper la tête et la queue de la liste chaque fois que vous calculez la moyenne.

Cela ressemble beaucoup à la suppression des valeurs aberrantes basées sur la médiane (c’est-à-dire que vous allez avoir besoin de deux passages sur les données, l’un pour trouver la médiane - ce qui est presque aussi lent que le tri des données à virgule flottante, l’autre pour calculer moyenne), mais nécessite moins de frais généraux au moment de l’établissement de la moyenne, au détriment du maintien d’une liste triée. Le choix le plus rapide dépendra entièrement de votre situation. Il se peut, bien sûr, que ce que vous souhaitiez vraiment, en tout cas, soit la médiane!

Si vous aviez des données discrètes (par exemple, octets = 256 valeurs possibles), vous pouvez utiliser 256 "bacs" d'histogramme avec un seul passage sur vos données, en comptant les valeurs qui entrent dans chaque chutier, il est très facile de trouver le médiane / approximative de la moyenne / suppression des valeurs aberrantes, etc. Ceci serait mon option préférée si vous pouviez vous permettre de perdre une partie de la précision de vos données, suivie du maintien d'une liste triée, si cela convient pour vos données.

Un moyen rapide pourrait être de prendre la médiane, puis les moyennes de nombres proches de la médiane.

"Pas si loin," être dépendant de votre projet.

Pour déterminer les valeurs aberrantes probables, une bonne règle empirique consiste à calculer la Interquartile Range (IQR) , puis toutes les valeurs situées à 1,5 * IQR du quartile le plus proche sont des valeurs aberrantes.

Il s'agit de la méthode de base utilisée par de nombreux systèmes de statistiques (comme R) pour détecter automatiquement les valeurs éloignées.

Toute méthode statistiquement significative et une bonne façon de l’aborder (Dark Eru, Daniel White) sera trop intense en informatique pour être répétée, et je pense avoir trouvé un moyen de contourner ce problème, ce qui permettra une correction ultérieure il non mis à la terre).

Merci pour les suggestions. Je les examinerai si j’ai le temps et si je veux savoir si leur gain vaut le ralentissement.

Voici une méthode rapide et sale que j'ai utilisée auparavant (fonctionne bien s'il y a très peu de valeurs aberrantes au début et que vous n'avez pas de conditions très compliquées pour ce qui constitue une valeur aberrante)

L'algorithme est O (N). La seule partie vraiment chère est la division.

Le véritable avantage ici est que vous pouvez le faire fonctionner en quelques minutes.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top