2016-03-28 20 views
8

Önceden açıklığa kavuşturmak istiyorum Streams kullanarak standart sapmayı hesaplamanın bir yolunu arıyorum (Şu anda & değerini döndüren ancak Streams kullanmadan hesaplayan bir çalışma yöntemim var).Java Akımları - Standart Sapma

Veri kümesi Link'da görüldüğü gibi eşleştirmelerle çalışıyorum. Bu bağlantıda gösterildiği gibi, verilerimi gruplandırdım & ortalamayı al, ancak SD'yi nasıl alacağımı anlayamıyorum.

Kod

outPut.stream() 
      .collect(Collectors.groupingBy(e -> e.getCar(), 
        Collectors.averagingDouble(e -> (e.getHigh() - e.getLow())))) 
      .forEach((car,avgHLDifference) -> System.out.println(car+ "\t" + avgHLDifference)); 

Ben de DoubleSummaryStatistics üzerinde Link kontrol ama SD için yardımcı görünmüyor.

cevap

9

Bu görev için kare toplamını hesaplayan özel bir toplayıcı kullanabilirsiniz. Buit-in DoubleSummaryStatistics toplayıcı bunu takip etmiyor. Bu uzman grubu in this thread tarafından tartışıldı, ancak nihayet uygulanmadı. Karelerin toplamı hesaplanırken karşılaşılan zorluk, ortadaki sonuçların karesini çizerken potansiyel taşmadır.

static class DoubleStatistics extends DoubleSummaryStatistics { 

    private double sumOfSquare = 0.0d; 
    private double sumOfSquareCompensation; // Low order bits of sum 
    private double simpleSumOfSquare; // Used to compute right sum for non-finite inputs 

    @Override 
    public void accept(double value) { 
     super.accept(value); 
     double squareValue = value * value; 
     simpleSumOfSquare += squareValue; 
     sumOfSquareWithCompensation(squareValue); 
    } 

    public DoubleStatistics combine(DoubleStatistics other) { 
     super.combine(other); 
     simpleSumOfSquare += other.simpleSumOfSquare; 
     sumOfSquareWithCompensation(other.sumOfSquare); 
     sumOfSquareWithCompensation(other.sumOfSquareCompensation); 
     return this; 
    } 

    private void sumOfSquareWithCompensation(double value) { 
     double tmp = value - sumOfSquareCompensation; 
     double velvel = sumOfSquare + tmp; // Little wolf of rounding error 
     sumOfSquareCompensation = (velvel - sumOfSquare) - tmp; 
     sumOfSquare = velvel; 
    } 

    public double getSumOfSquare() { 
     double tmp = sumOfSquare + sumOfSquareCompensation; 
     if (Double.isNaN(tmp) && Double.isInfinite(simpleSumOfSquare)) { 
      return simpleSumOfSquare; 
     } 
     return tmp; 
    } 

    public final double getStandardDeviation() { 
     return getCount() > 0 ? Math.sqrt((getSumOfSquare()/getCount()) - Math.pow(getAverage(), 2)) : 0.0d; 
    } 

} 

Sonra değerleri aynı anahtar için high - low standart sapmaya karşılık nerede harita haline girdi listesini toplayacak

Map<String, Double> standardDeviationMap = 
    list.stream() 
     .collect(Collectors.groupingBy(
      e -> e.getCar(), 
      Collectors.mapping(
       e -> e.getHigh() - e.getLow(), 
       Collector.of(
        DoubleStatistics::new, 
        DoubleStatistics::accept, 
        DoubleStatistics::combine, 
        d -> d.getStandardDeviation() 
       ) 
      ) 
     )); 

Bu ile bu sınıfı kullanabilirsiniz.

+0

çok teşekkür ederim. SD'yi alabiliyorum. Şimdi, iki akış yerine aynı akış() çağrısında hem ortalamaDouble hem de SD (like - car, averageHL, SD) toplayıp toplayamadığımı kontrol ediyorum. – iCoder

+1

@iCoder Bu cevapta 'DoubleStatistics' SD ve ortalama evet toplar. Tüm bilgi ile bir 'Harita ' olabilir. – Tunaki

+2

Taşma ile ilgili ilginç gerçek şu ki: “LongSummaryStatistics” aslında toplamı aşar, yani LongStream.of (Long.MAX_VALUE, Long.MAX_VALUE) .summaryStatistics(). GetAverage() '-1.0' dir. Bu taşma vurmak için şans, benim düşünceme göre kareler toplamı taşma şansı daha yüksektir ... –