Il modo migliore per utilizzare le funzioni di statistiche math.net sulle proprietà degli oggetti in un elenco
-
21-12-2019 - |
Domanda
Sto cercando di capire il modo migliore per eseguire un calcolo velocemente e volevo scoprire che tipo di approccio le persone di solito assumono una situazione come questa.
Ho un elenco di oggetti che hanno proprietà che voglio calcolare la deviazione media e standard di . Pensavo di usare Questa libreria math.net sarebbe probabilmente più facile / ottimizzato per le prestazioni.
Sfortunatamente, gli argomenti di input per queste funzioni sono array. La mia unica soluzione è scrivere la mia funzione per calcolare i mezzi e le STD? Potrei scrivere una sorta di metodo di estensione per gli elenchi che utilizza le funzioni Lambda come qui ? Oppure sto meglio di scrivere funzioni che restituiscono gli array delle proprietà dell'oggetto e usano questi con math.net.
Presumibilmente la risposta dipende da alcune cose come le dimensioni della lista? Diciamo per l'argomento che la lista ha 50 elementi. La mia preoccupazione è puramente prestazioni.
Soluzione
ArrayStatistics
Aspetta effettivamente gli array in quanto è ottimizzato per questo caso speciale (è per questo che è chiamato Arraystatistics).Allo stesso modo, StreamingStatistics
è ottimizzato per lo streaming di sequenza di Ienumarableless senza mantenere i dati in memoria.La classe generale che funziona con tutti i tipi di input è la classe Statistics
.
Hai verificato che semplicemente usare LINQ e StreamingStatistics non è abbastanza veloce nel tuo caso di utilizzo?In calcolo di queste statistiche per un elenco di puramente 50 voci è a malapena misurabile, a meno che, a meno che non lo fai un milione di volte in un loop.
Esempio con Math.net Numerics V3.0.0-Alpha7, utilizzando Tuples in un elenco per emulare i tipi personalizzati:
using MathNet.Numerics.Statistics;
var data = new List<Tuple<string, double>>
{
Tuple.Create("A", 1.0),
Tuple.Create("B", 2.0),
Tuple.Create("C", 1.5)
};
// using the normal extension methods within `Statistics`
var stdDev1 = data.Select(x => x.Item2).StandardDeviation();
var mean1 = data.Select(x => x.Item2).Mean();
// single pass variant (unfortunately there's no single pass MeanStdDev yet):
var meanVar2 = data.Select(x => x.Item2).MeanVariance();
var mean2 = meanVar2.Item1;
var stdDev2 = Math.Sqrt(meanVar2.Item2);
// directly using the `StreamingStatistics` class:
StreamingStatistics.MeanVariance(data.Select(x => x.Item2));
. Altri suggerimenti
La soluzione più capatica che è possibile utilizzare è mettere linq in modo da trasformare List
su array
List<SomeClass> list = ...
GetMeanAndStdError(list.ToArray()); // <- Not that good performance
.
Tuttavia, se la performance è la tua preoccupazione, preferiresti calcolare esplicitamente la media e la varianza (scrivi la tua funzione):
List<SomeClass> list = ...
Double sumX = 0.0;
Double sumXX = 0.0;
foreach (var item in list) {
Double x = item.SomeProperty;
sumX += x;
sumXX += x * x;
}
Double mean = sumX / list.Count;
Double variance = (sumXX / list.Count - mean);
.