2011년 9월 8일 목요일

[ArcObjects] ArcObjects에서 필드의 통계정보 계산하기

ArcObjects에서 필드의 통계정보를 계산하는 IDataStatistics라는 인터페이스가 있습니다.

아래 C# 코드는 다음과 같습니다.
 - IDataStatistics 인터페이스를 이용하여 하나의 필드를 계산
 - ICursor 인터페이스를 이용하여 하나의 필드를 계산
 - ICursor 인터페이스를 이용하여 여러 필드를 계산

▣ ArcObjects  IDataStatistics

▣ Code Snippet

using System;
using System.Diagnostics;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.esriSystem;
using System.Collections.Generic;

○  IDataStatistics 인터페이스를 이용하여 하나의 필드를 계산
public static void DataStatistics() {
    IFeatureClass featureClass = OpenShapefile(shapefilePath);
    string fieldName = "POP2008";

    IQueryFilter queryFilter = new QueryFilterClass();
    queryFilter.SubFields = fieldName;

    ICursor cursor = (ICursor)featureClass.Search(queryFilter, true);

    IDataStatistics dataStatistics = new DataStatisticsClass();
    dataStatistics.Field = fieldName;
    dataStatistics.Cursor = cursor;

    // -1 means pull all records
    dataStatistics.SampleRate = -1; 

    IStatisticsResults sr = dataStatistics.Statistics;

    Debug.WriteLine(string.Format("Count = {0}", sr.Count));
    Debug.WriteLine(string.Format("Minimum = {0}", sr.Minimum));
    Debug.WriteLine(string.Format("Maximum = {0}", sr.Maximum));
    Debug.WriteLine(string.Format("Sum = {0}", sr.Sum));
    Debug.WriteLine(string.Format("Mean = {0}", sr.Mean));
    Debug.WriteLine(string.Format("Variance = {0}", Math.Pow(sr.StandardDeviation, 2)));
    Debug.WriteLine(string.Format("Standard Deviation = {0}", sr.StandardDeviation));

    System.Runtime.InteropServices.Marshal.ReleaseComObject(cursor);
}

○  ICursor 인터페이스를 이용하여 하나의 필드를 계산
public static void DataStatistics2() {
    IFeatureClass featureClass = OpenShapefile(shapefilePath);
    string fieldName = "POP2008";

    int fieldID = featureClass.FindField(fieldName);
    double minVal = double.MaxValue;
    double maxVal = double.MinValue;
    double sumOfVals = 0;
    double sumOfSqrs = 0;

    int rowCount = 0;

    IQueryFilter queryFilter = new QueryFilterClass();
    queryFilter.SubFields = fieldName;

    ICursor cursor = (ICursor)featureClass.Search(queryFilter, true);
    IRow row = cursor.NextRow();
    while (row != null) {
        rowCount++;

        double val = Convert.ToDouble(row.get_Value(fieldID));

        minVal = Math.Min(minVal, val);
        maxVal = Math.Max(maxVal, val);
        sumOfVals += val;
        sumOfSqrs += Math.Pow(val, 2.0);

        row = cursor.NextRow();
    }
    System.Runtime.InteropServices.Marshal.ReleaseComObject(cursor);

    Debug.WriteLine(string.Format("Count = {0}", rowCount));
    Debug.WriteLine(string.Format("Minimum = {0}", minVal));
    Debug.WriteLine(string.Format("Maximum = {0}", maxVal));
    Debug.WriteLine(string.Format("Sum = {0}", sumOfVals));
    Debug.WriteLine(string.Format("Mean = {0}", sumOfVals / rowCount));

    double variance = (sumOfSqrs - Math.Pow(sumOfVals, 2) / rowCount) / (rowCount - 1);
    Debug.WriteLine(string.Format("Variance = {0}", variance));
    Debug.WriteLine(string.Format("Standard Deviation = {0}", Math.Sqrt(variance)));
}

○  ICursor 인터페이스를 이용하여 여러 필드를 계산
public static void DataStatistics3() {
    IFeatureClass featureClass = OpenShapefile(shapefilePath);
    string[] fieldNames = { "POP2008", "POP2009", "POP2010" };

    int fieldCount = fieldNames.Length;

    int[] fieldID = new int[fieldCount];
    double[] minVal = new double[fieldCount];
    double[] maxVal = new double[fieldCount];
    double[] sumOfVals = new double[fieldCount];
    double[] sumOfSqrs = new double[fieldCount];
    
    for (int k = 0; k < fieldCount; k++) {
        fieldID[k] = featureClass.FindField(fieldNames[k]);
        minVal[k] = double.MaxValue;
        maxVal[k] = double.MinValue;
        sumOfVals[k] = 0;
        sumOfSqrs[k] = 0;
    }

    int rowCount = 0;
    IQueryFilter queryFilter = new QueryFilterClass();
    queryFilter.SubFields = string.Join(",", fieldNames);

    ICursor cursor = (ICursor)featureClass.Search(queryFilter, true);
    IRow row = cursor.NextRow();
    while (row != null) {
        rowCount++;
        for (int k = 0; k < fieldCount; k++) {
            double val = Convert.ToDouble(row.get_Value(fieldID[k]));

            minVal[k] = Math.Min(minVal[k], val);
            maxVal[k] = Math.Max(maxVal[k], val);
            sumOfVals[k] += val;
            sumOfSqrs[k] += Math.Pow(val, 2.0);
        }
        row = cursor.NextRow();
    }
    System.Runtime.InteropServices.Marshal.ReleaseComObject(cursor);
    
    for (int k = 0; k < fieldCount; k++) {
        Debug.WriteLine(string.Format("Field Name = {0}", fieldNames[k]));
        Debug.WriteLine(string.Format("Count = {0}", rowCount));
        Debug.WriteLine(string.Format("Minimum = {0}", minVal[k]));
        Debug.WriteLine(string.Format("Maximum = {0}", maxVal[k]));
        Debug.WriteLine(string.Format("Sum = {0}", sumOfVals[k]));
        Debug.WriteLine(string.Format("Mean = {0}", sumOfVals[k] / rowCount)); 

        double variance = (sumOfSqrs[k] - Math.Pow(sumOfVals[k], 2) / rowCount) / (rowCount - 1);
        Debug.WriteLine(string.Format("Variance = {0}", variance));
        Debug.WriteLine(string.Format("Standard Deviation = {0}", Math.Sqrt(variance)));
    }
}