Melhor maneira de usar funções estatísticas do Math.NET nas propriedades de objetos em uma lista

StackOverflow https://stackoverflow.com//questions/22012737

Pergunta

Estou tentando descobrir a melhor maneira de realizar um cálculo rápido e queria descobrir que tipo de abordagem as pessoas normalmente adotariam em uma situação como essa.

Eu tenho uma lista de objetos que possuem propriedades das quais desejo calcular a média e o desvio padrão.pensei em usar esse A biblioteca Math.NET provavelmente seria mais fácil/otimizada para desempenho.

Infelizmente, os argumentos de entrada para estas funções são arrays.Minha única solução é escrever minha própria função para calcular meios e DSTs?Posso escrever algum tipo de método de extensão para listas que usem funções lambda como aqui?Ou é melhor escrever funções que retornem matrizes das propriedades do meu objeto e usá-las com o Math.NET.

Presumivelmente, a resposta depende de algumas coisas como o tamanho da lista?Digamos, para fins de argumentação, que a lista tenha 50 elementos.Minha preocupação é puramente desempenho.

Foi útil?

Solução

ArrayStatistics na verdade, espera arrays, pois é otimizado para este caso especial (é por isso que é chamado de ArrayStatistics).De forma similar, StreamingStatistics é otimizado para streaming de sequência IEnumerable sem manter dados na memória.A classe geral que funciona com todos os tipos de entrada é a Statistics aula.

Você verificou que simplesmente usar LINQ e StreamingStatistics não é rápido o suficiente no seu caso de uso?Calcular essas estatísticas para uma lista de apenas 50 entradas quase não é mensurável, a menos que você faça isso um milhão de vezes seguidas.

Exemplo com Math.NET Numerics v3.0.0-alpha7, usando tuplas em uma lista para emular seus tipos personalizados:

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));

Outras dicas

A solução mais fácil que você pode usar é colocar Linq então isso transforma List para variedade

  List<SomeClass> list = ...

  GetMeanAndStdError(list.ToArray()); // <- Not that good performance

No entanto, se o desempenho é sua preocupação, você prefere calcular a Média e a Variância explicitamente (escreva sua própria função):

  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);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top