2016-03-28 11 views
8

मैं ऊपर स्पष्ट करना चाहता हूं मैं स्ट्रीम का उपयोग कर मानक विचलन की गणना करने के लिए एक तरीका ढूंढ रहा हूं (मेरे पास वर्तमान में एक कार्य विधि है जो & एसडी देता है लेकिन स्ट्रीम का उपयोग किए बिना)।जावा स्ट्रीम - मानक विचलन

डेटासेट मैं Link में देखे गए मैचों के साथ मिलकर काम कर रहा हूं। जैसा कि इस लिंक में दिखाया गया है, मेरा डेटा & समूह प्राप्त करने में सक्षम है, लेकिन औसत प्राप्त करने में सक्षम नहीं है, लेकिन यह पता लगाने में सक्षम नहीं है कि एसडी कैसे प्राप्त करें।

कोड

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

मैं भी DoubleSummaryStatistics पर Link जाँच की लेकिन इसके लिए एसडी मदद करने के लिए प्रतीत नहीं होता।

उत्तर

9

आप इस कार्य के लिए कस्टम कलेक्टर का उपयोग कर सकते हैं जो वर्ग के योग की गणना करता है। DoubleSummaryStatistics कलेक्टर में बिट-इन इसका ट्रैक नहीं रखता है। इस पर विशेषज्ञ समूह in this thread द्वारा चर्चा की गई लेकिन अंततः लागू नहीं हुई। मध्यवर्ती परिणामों को स्क्वायर करते समय वर्गों के योग की गणना करते समय कठिनाई संभावित अतिप्रवाह है।

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

} 

उसके बाद, आप

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

इस के साथ इस वर्ग का उपयोग किसी नक्शे में इनपुट सूची एकत्रित करेगा जहां मूल्यों एक ही कुंजी के लिए high - low के मानक विचलन से मेल खाती है सकते हैं।

+0

आपको बहुत बहुत धन्यवाद। मैं एसडी प्राप्त करने में सक्षम हूँ। अब मैं यह देखने के लिए जांच कर रहा हूं कि क्या मैं दो धाराओं के बजाय एक ही स्ट्रीम() कॉल में औसत और डबल (एसडी, जैसे कार, औसत एचएल, एसडी) औसत एकत्र कर सकता हूं। – iCoder

+1

@iCoder इस उत्तर में 'डबलस्टैटिक्स' एसडी और औसत हां एकत्र करता है। आपके पास सभी जानकारी के साथ 'मानचित्र <स्ट्रिंग, डबलस्टैटिक्स>' हो सकता है। – Tunaki

+2

अतिप्रवाह के बारे में दिलचस्प तथ्य: कोई भी इस बात पर परवाह नहीं करता कि 'LongSummaryStatistics' वास्तव में योग को ओवरफ़्लो करता है, इसलिए 'LongStream.of (Long.MAX_VALUE, Long.MAX_VALUE) .समरीस्टैटिक्स()। GetAverage() '' -1.0' है। इस ओवरफ्लो को मारने की संभावनाएं, मेरी राय के लिए समर-ऑफ-स्क्वायर ओवरफ्लो हिट करने की संभावना से अधिक है ... –

संबंधित मुद्दे