3

I'm new to Python and I need a script that can split my huge shapefile based on a certain attribute.

SO what I have is a big shapefile (over 3M records) with a field named "NISCODE". In this code are values ranging from 11001 to 73109. But only the first number of the value is important to me, that's the base on which the shapefile needs to be split on. So I need 7 shapefiles; everything starting with 1, with 2,... enter image description here

I know I'll probably need a for loop, but I don't know how to put it in my code correctly. Here is what I have so far, this was just a test to see if I could already make a selection for the 1st part (everything starting with 1...), but already that fails.

# Import system modules
import arcpy
from arcpy import env
env.overwriteOutput="True"

# Set workspace
# setting the environment
workspacedir= r"C:\..."
env.workspace= workspacedir

shp = r"C:\....\Adp.shp"

r=arcpy.Exists("Adp.shp")
print r
### Make a layer from the feature class
arcpy.MakeFeatureLayer_management("Adp.shp", "Vl_lyr")
##
# Wselect only those that have id starting with 1
arcpy.SelectLayerByAttribute_management("Vl_lyr", "NEW_SELECTION", ' "NISCODE" = 1* ')
##
# Write the selected features to a new featureclass
arcpy.CopyFeatures_management("Vl_lyr", "Vlaanderen_1.shp")

EDIT:

The new code looks now like this:`

# Import system modules
import arcpy
from arcpy import env
env.overwriteOutput="True"

# Set workspace
# setting the environment
workspacedir= r"C:\..."
env.workspace= workspacedir

shp = r"C:\...\Adp.shp"

arcpy.AddField_management(shp, "newNISCODE", "TEXT")

arcpy.CalculateField_management(shp, "newNISCODE", '"newNISCODE" = NISCODE[0]', "PYTHON")

list = []
with arcpy.da.SearchCursor(fc, "newNICODE") as cursor:
    for row in cursor:
        list.append(row)
num_list = sorted(set(list))

for i in range(1, len(num_list)):
    arcpy.Select_analysis(shp, "{}_shp".format(i), 'newNICODE = "{}"'.format(i))`

but the code fails on the Calculatefield step:

Traceback (most recent call last):
  File "C:\...\SplitShape.py", line 15, in <module>
    arcpy.CalculateField_management(shp, "newNISCODE", '"newNISCODE" = NISCODE[0]', "PYTHON")
  File "C:\Program Files (x86)\ArcGIS\Desktop10.5\ArcPy\arcpy\management.py", line 3663, in CalculateField
    raise e
ExecuteError: ERROR 000539: SyntaxError: invalid syntax (<expression>, line 1)
Failed to execute (CalculateField).
3
  • 2
    Please paste the code as text not as an image.
    – ahmadhanb
    Jun 27, 2017 at 8:04
  • If it is not priority for you to write the script, maybe you could use field calculator to leave just the first number in "NISCODE" (which you need), and then do a split by attribute tool.
    – Dean7
    Jun 27, 2017 at 8:12
  • Sorry, I pasted the code now as text. @Dean7 I do need to write a script for this. Jun 27, 2017 at 8:32

2 Answers 2

2

you don't need to compute a new field. In your code, the first problem is that you handle the NISCODE field as a numeric field, but it can be seen that it is actually a text field (text are left aligned, number are aligned right). Therefore you need ' ' around the value. Second, if you test with a wildcard you must use LIKE and not =. Third, the SQL wildcard character is % (or _ for a single character). So instead of:

arcpy.SelectLayerByAttribute_management("Vl_lyr", "NEW_SELECTION", ' "NISCODE" = 1* ')

it should be

arcpy.SelectLayerByAttribute_management("Vl_lyr", "NEW_SELECTION", """ "NISCODE" LIKE '1%' """) 

Alternatively, you could use some SQL syntax to take only the first character

arcpy.SelectLayerByAttribute_management("Vl_lyr", "NEW_SELECTION", """ LEFT("NISCODE",1) = '1' """) 

then you can make a loop:

mylist = []
with arcpy.da.SearchCursor(shp, "NISCODE") as cursor:
    for row in cursor:
        mylist.append(row[0])
num_list = list(set(mylist))
for i in num_list:
    arcpy.Select_analysis(shp, shp[:-4] + i +".shp", """ Left("NISCODE",1) = '{}'""".format(i))

Note that shp fieldnames must be written between " " , but it would not be the case in gdb.

As a remark, your calculate field expression is not working because 1) you mustn't write the target fiel name in the expression and 2) python field names should be written with ! !.

1

You could add a new field, and calculate that field based on the field you need. Using python, we can recalculate it to only contain the first digit. It looks like the NISCODE is text so try this:

arcpy.AddField_management(shp, "newNISCODE", "TEXT")

arcpy.CalculateField_management(shp, "newNISCODE", '!NISCODE![0]', "PYTHON")

list = []
with arcpy.da.SearchCursor(shp, "newNICODE") as cursor:
    for row in cursor:
        list.append(row)
new_list = sorted(set(list))
num_list = [item for t in new_list for item in t]

for codenum in num_list:
    arcpy.Select_analysis(shp, 'shp_' + codenum + '.shp',  'newNISCODE' = codenum)
21
  • I badly expressed myself I think in my explanation. So my desired shapefiles should be split based on the first number of the NISCODE, but I still need to have the whole NISCODE in the end. So I don't need new shapefiles with NISCODE 1,2,3,4,5,6,7; but a shapefile containing all NISCODE's that start with 1, start with 2, and so on... Jun 27, 2017 at 8:33
  • This tool is only available at 10.5. I use the Split tool and it works.
    – MacroZED
    Jun 27, 2017 at 8:35
  • @MacroZED I wanted to comment my adjustments here, but I couldn't use the nice "code layout" here, so it looked like a mess. Therefore I used "answer" to show it. Where do I have to post my adjustments? Or just edit my first post? Jun 27, 2017 at 9:02
  • 1
    @MacroZED +1, but you should edit your code, because you take the values of the range function instead of the values in the list.
    – radouxju
    Jun 27, 2017 at 9:57
  • 1
    finally, shp is a shapefile with extension .shp, so don't add codenum at the end, otherwise the extension will become invalid (e.g. Adp.shp1). And your quotes are not yet correct...
    – radouxju
    Jun 27, 2017 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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