Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm trying to count rows by unique values for a given FeatureClass. I'm using DataStatistics to get the unique values for a specific column for a given FeatureClass.

This seems to be (very) slow with big shapefiles (> 200k of features) - is there a faster way to determine unique values?

The second step of the process (using QueryFilter in combination with FeatureClass.FeatureCount()) seems fast enough although I would be glad if im pointed to a better solution.

public static Dictionary<string, int> CountUniquesStatistic(ITable table, string fldName)
{
    Dictionary<string, int> uniqueValuesDictionary = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);

    DataStatistics dataStatistics = new DataStatistics();
    dataStatistics.Field = fldName;
    dataStatistics.Cursor = table.Search(null, false);

    IEnumerator uniqueValues = dataStatistics.UniqueValues;

    while (uniqueValues.MoveNext())
    {
        object current = uniqueValues.Current;
        uniqueValuesDictionary[current.ToString()] = 0;
    }

    foreach (string key in uniqueValuesDictionary.Keys.ToList())
    {
        IQueryFilter queryFilter = new QueryFilter();
        queryFilter.WhereClause = string.Format("{0} = '{1}'", fldName, key);

        uniqueValuesDictionary[key] = table.RowCount(queryFilter);
    }

    return uniqueValuesDictionary;
}
share|improve this question
2  
Related: NIM087476 is bug introduced at 10.1SP1 and is a memory leak for UniqueValues. –  Jay Cummins Feb 25 '13 at 19:51
    
Do you need to incorporate this into an application? If you want the best performance, why not transfer the data into a database and run a sql group by with count -- super fast even with Access? –  awesomo Feb 26 '13 at 17:51
    
I have to build an ArcMap Addin and calculate statistics based on selected featureclass columns - waiting 10 seconds for the user is not the end of the world, but not convenient either... –  Dresel Feb 26 '13 at 18:02

1 Answer 1

I haven't tested this code, but I'd be very interested in how it compares performance-wise with DataStatistics. Maybe use recycling=true when you call Search to for the cursor for datastatistics for a fair comparison. Cast the IFeatureclass to ITable when calling this. I'm also curious how this would compare to python.

public static Dictionary<string, int> CountUniques(ITable table, string fldName)
{
    int idx = table.Fields.FindField(fldName);
    if(idx == -1)
    {
        throw new Exception(string.Format(
            "field {0} not found in {1}",
            fldName,((IDataset)table).Name));
    }
    IQueryFilter qf = new QueryFilterClass();
    qf.AddField(fldName);

    var outDict = new Dictionary<string,int>(StringComparer.CurrentCultureIgnoreCase);
    ICursor cur = null;
    IRow row = null;
    try
    {
        cur = table.Search(qf, true);
        while ((row = cur.NextRow()) != null)
        {
            string key = row.get_Value(idx) is DBNull ? "<Null>" :
                row.get_Value(idx).ToString();
            if (!outDict.ContainsKey(key))
                outDict[key] = outDict[key] + 1;
            else
                outDict.Add(key, 1);
        }
    }
    catch(Exception ex)
    {
        string msg = row == null ? "error getting value" :
            "error getting value for row " + row.OID.ToString();
        throw new Exception(msg, ex);
    }
    finally
    {
        if(cur != null)
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cur);
    }

    return outDict;
}
share|improve this answer
    
Sadly it is approximately 4-5 times slower than DataStatistics and FeatureCount combination. –  Dresel Feb 26 '13 at 17:14
    
@Dresel oh well. I guess that's the cost of more traffic through the interop(?) If it's an issue of blocking the UI, have you considered using a BackgroundWorker ? –  Kirk Kuykendall Feb 26 '13 at 20:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.