2010-06-29 6 views
45

일반 목록의 표준 편차를 계산해야합니다. 내 코드를 포함 시키려고 노력할 것이다. 그 안에 데이터가있는 일반적인 목록입니다. 데이터는 주로 float 및 int입니다.일반 목록의 표준 편차?

다음
namespace ValveTesterInterface 
{ 
    public class ValveDataResults 
    { 
     private List<ValveData> m_ValveResults; 

     public ValveDataResults() 
     { 
      if (m_ValveResults == null) 
      { 
       m_ValveResults = new List<ValveData>(); 
      } 
     } 

     public void AddValveData(ValveData valve) 
     { 
      m_ValveResults.Add(valve); 
     } 

는 표준 편차를 계산해야하는 기능입니다 : 여기에 많은 세부 사항에 들어가기없이 상대 내 코드는

 public float LatchStdev() 
     { 

      float sumOfSqrs = 0; 
      float meanValue = 0; 
      foreach (ValveData value in m_ValveResults) 
      { 
       meanValue += value.LatchTime; 
      } 
      meanValue = (meanValue/m_ValveResults.Count) * 0.02f; 

      for (int i = 0; i <= m_ValveResults.Count; i++) 
      { 
       sumOfSqrs += Math.Pow((m_ValveResults - meanValue), 2); 
      } 
      return Math.Sqrt(sumOfSqrs /(m_ValveResults.Count - 1)); 

     } 
    } 
} 

은 뭐죠 LatchStdev 내부 무시() 함수는 그것이 옳지 않다는 것을 확신하기 때문에. 그것의 다만 나의 가난한 시도는 st dev를 계산한다. 나는 일반 데이터 목록의 목록이 아닌 복식 목록을 수행하는 방법을 알고 있습니다. 누군가이 경험이 있으면 도움을주십시오.

답변

48

This article이 도움이 될 것입니다. 시퀀스 double 값의 편차를 계산하는 함수를 만듭니다. 적절한 데이터 요소의 순서를 제공하면됩니다.

결과 기능은 다음과 같습니다이 너무 오래 우리는 값에 대한 선택 계산되고를 제공하기 때문에, 어떤 일반적인 유형에 적응할 수있을만큼 쉽게

private double CalculateStdDev(IEnumerable<double> values) 
{ 
    double ret = 0; 
    if (values.Count() > 0) 
    {  
    //Compute the Average  
    double avg = values.Average(); 
    //Perform the Sum of (value-avg)_2_2  
    double sum = values.Sum(d => Math.Pow(d - avg, 2)); 
    //Put it all together  
    ret = Math.Sqrt((sum)/(values.Count()-1)); 
    } 
    return ret; 
} 

. LINQ가 좋은 곳입니다의 Select funciton는 사용자 정의 형식의 제네릭 목록에서 표준 편차를 계산하기위한 숫자 값의 순서를 투사 할 수 있습니다 :

List<ValveData> list = ... 
var result = list.Select(v => (double)v.SomeField) 
       .CalculateStdDev(); 
+0

내 C#에는 평균이 없습니다. 그것은 나타나지 않습니다. 그게 내 문제 중 하나 야. 또한 필자는 함수를 매개 변수로 사용하여 일반 목록을 전달할 수 없습니다. 위의 코드처럼 stdevmethod 내부에서 구현해야합니다. 내 표준 편차가 벗어났다. –

+0

또한들. C#에는 평균 (Math.average)이 없습니다. 그래서 위의 코드와 같은 평균을 계산합니다. 가장 문제가있는 표준 편차입니다. Thanks –

+1

@Tom Hangler, 파일의 맨 위에'using System.Linq; '를 추가하여 LINQ 함수 라이브러리를 포함시켜야합니다. 여기에는 'Average()'와 'Select()'가 모두 포함됩니다. – LBushkin

125

위의 예는 약간 잘못하고있을 수 있습니다 인구수 집합이 1이면 0으로 나누십시오. 다음 코드는 다소 간단하고 "모집단 표준 편차"결과를 제공합니다. 허용 대답은 수학적으로 올바른 것 같다 비록 (http://en.wikipedia.org/wiki/Standard_deviation)

using System; 
using System.Linq; 
using System.Collections.Generic; 

public static class Extend 
{ 
    public static double StandardDeviation(this IEnumerable<double> values) 
    { 
     double avg = values.Average(); 
     return Math.Sqrt(values.Average(v=>Math.Pow(v-avg,2))); 
    } 
} 
+8

+1 단순화를 위해 –

+1

이 답변을해야합니다, 표준 편차를 계산하는 LBushkin에 의해 답변을 반대로 샘플 표준 편차 – Wouter

+0

명함을 단순하게 계산합니다. 잘 했어. – PseudoToad

17

, 그것은 프로그래밍 관점에서 잘못된 - 동일한 순서 4 번을 열거합니다. 기본 객체가 목록이나 배열이지만 입력이 필터링 된/집계 된/etc linq 표현식이거나 데이터가 데이터베이스 또는 네트워크 스트림에서 직접 오는 경우 이는 훨씬 낮은 성능을 초래합니다.

휠을 재발행하지 말고 더 나은 오픈 소스 수학 라이브러리 인 Math.NET을 사용하지 않을 것을 적극 권장합니다. 우리는 우리 회사에서 그 lib를 사용하고 있으며 성능에 매우 만족합니다.

PM> 설치 - 패키지 MathNet.Numerics는

var populationStdDev = new List<double>(1d, 2d, 3d, 4d, 5d).PopulationStandardDeviation(); 

var sampleStdDev = new List<double>(2d, 3d, 4d).StandardDeviation(); 

자세한 내용은 http://numerics.mathdotnet.com/docs/DescriptiveStatistics.html를 참조하십시오.

마지막으로는, 가장 빠른 결과를 얻을 수 및 일부 정밀도를 희생하고자하는 사람들을 위해, "한 패스"알고리즘을 읽어 https://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods

0

난 당신이 무슨 일을하는지보고, 나는 비슷한 것을 사용합니다. 네가 충분히 멀리 가지 않는 것 같아. 모든 데이터 처리를 하나의 클래스로 캡슐 화하는 경향이 있으므로 목록이 변경 될 때까지 계산 된 값을 캐시 할 수 있습니다.예를 들어 :

public class StatProcessor{ 
private list<double> _data; //this holds the current data 
private _avg; //we cache average here 
private _avgValid; //a flag to say weather we need to calculate the average or not 
private _calcAvg(); //calculate the average of the list and cache in _avg, and set _avgValid 
public double average{ 
    get{ 
    if(!_avgValid) //if we dont HAVE to calculate the average, skip it 
     _calcAvg(); //if we do, go ahead, cache it, then set the flag. 
    return _avg; //now _avg is garunteed to be good, so return it. 
    } 
} 
...more stuff 
Add(){ 
//add stuff to the list here, and reset the flag 
} 
} 

당신은이 방법을 사용하면, 평균에 대한 첫 번째 요청이 실제로 평균을 계산하는 것을 알 수 있습니다. 그 후, 우리가 목록에서 아무것도 추가 (또는 제거하거나 전혀 수정하지 않았지만 수정)하지 않는 한 기본적으로 아무 것도 얻지 못합니다.

또한 평균은 표준 편차에 대한 알고리즘에서 사용되므로 표준 편차를 계산하면 평균값을 얻지 못하고 평균을 먼저 계산하면 표준 편차 계산이 약간 향상됩니다. 우리가 깃발을 확인하는 것을 기억한다고 가정합니다.

더욱! 어쨌든 모든 값을 루핑하는 평균 함수와 같은 장소는 최소값과 최대 값과 같은 항목을 캐시 할 수있는 좋은 시간입니다. 물론이 정보에 대한 요청은 먼저 캐싱되었는지 여부를 확인해야하며, 목록을 사용하여 최대 값을 찾는 것과 비교할 때 상대적으로 느려질 수 있습니다. 모든 추가 작업이 관련 캐시를 설정하기 때문에 귀하의 액세스.

관련 문제