1

I have a large shapefile filled with soil information. I am tyring to figure out the best method to classify this soil based on the description into 5 different categories. 1. Clay 2. Sandy 3. Loam 4. Silt 5. Eroded

I have done this manually with smaller datasets. However, I am trying to figure out a way to automate this process.

This is what the dataset looks like:

enter image description here

  • 1
    field calculator with code snippet, use if elif and else statements.... – NULL.Dude Jul 23 '18 at 18:20
  • What if you labeled it or used symbology and gave a unique field to base the labeling or symbology on. – enolan Jul 23 '18 at 20:08
  • Derive first part of description before comma, summarise and give it to soil scientist to fill 2nd column with new categories. – FelixIP Jul 23 '18 at 20:28
1

You can use Python and the da.UpdateCursor. This is an example which you can modify. Im using difflib.SequenceMatcher.ratio to handle the fact that the words dont always match completely, for example Silt and Silty. The classification is made by the last occurence of category in each description. The classification will likely not be 100% correct so you will need to check and correct the results.

from difflib import SequenceMatcher
import arcpy

fc = 'C:\folder\shapefile.shp' #Modify to match your data
descfield = 'DESC' #Modify to match your data
categoryfield = 'Category' #Modify to match your data. Add this field as type text/string

def soilclass(inputstring):
    cats = ['CLAY','SANDY','LOAM','SILT','ERODED']
    ratiolimit = 0.7 #Adjust
    inputstring=inputstring.replace(',','').upper().split()
    newdesc = []
    for word in inputstring:
        for cat in cats:
            if SequenceMatcher(a=word, b=cat).ratio()>=ratiolimit:
                newdesc.append(cat)
    if len(newdesc)>0:
        value = newdesc[-1].capitalize() #Categorize by last word in newdesc, for example Eroded
    else:
        value = 'Cant categorize'
    return value

with arcpy.da.UpdateCursor(fc,[descfield,categoryfield]) as cursor:
    for row in cursor:
        row[1] = soilclass(row[0])
        cursor.updateRow(row)

Example of function:

a = 'Eden flaggy silty clay, 20 to 30 percent slopes, severely eroded'
b = 'Otwood silt loamy, 2 to 6 percent slopes, rarely flooded'
c = 'dsffd sdffwf fdsfsd'

soilclass(a)
'Eroded'
soilclass(b)
'Loam'
soilclass(c)
'Cant categorize'
| improve this answer | |
  • I feel like this is the way to go about it. However, when trying to run this python script I keep returning this error.. raceback (most recent call last): File "C:/Users/eheidtm/python/soil_desc.py", line 25, in <module> for row in cursor: RuntimeError: A column was specified that does not exist. – Ethan Heidtman Jul 24 '18 at 12:02
  • 1
    You need to modify field names in the beginning of the script and also add the category field – BERA Jul 24 '18 at 12:07
1

I would start by creating a new field for class.

Use the select by attributes function and for each class

SELECT FROM "Soils Dataset" WHERE "DESC" LIKE '%eroded%';
SELECT FROM "Soils Dataset" WHERE "DESC" LIKE '%clay%';
SELECT FROM "Soils Dataset" WHERE "DESC" LIKE '%silt loam%';
etc...

At each selection use the field calculator on the new Class field and populate the selected fields with appropriate class name. It looks like there may be some overlap in classes and I would use a couple different variations on the descriptions to be ensure you catch everything.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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