Select to view content in your preferred language

Using SearchCursor and CalculateField

2327
3
Jump to solution
07-28-2014 04:19 AM
BenLeslie1
Regular Contributor

Hi - I'm trying to write a little bit of code to assign a random value to my ORIENT field where ORIENT = 0.

My problem is that it chages the ORIENT for the whole table not just where the value is zero.

I guess that this is because line 14 does not refer to row but I don't know how to charge it so it does refer to row - can anyone advise??

import arcpy

fc = r"c:\Test_Orient.shp"

feildName = "ORIENT"

expression = "rand_num()*360"

codeblock = """def rand_num():

    import random

    return random.random()"""

   

#search for rows to be altered

rows = arcpy.SearchCursor(fc, fieldName + " = 0")

for row in rows:

    arcpy.CalculateField_management(fc, fieldName, expression, "PYTHON_9.3", codeblock)

0 Kudos
1 Solution

Accepted Solutions
ChristopherMoravec1
New Contributor II

Ben,

It might be easier in this case (and probably faster) to simply us a feature layer and your calculate field.  I would try something like this:

import arcpy

fc = r"c:\Test_Orient.shp" 

feildName = "ORIENT" 

expression = "rand_num()*360" 

codeblock = """def rand_num():

    import random

    return random.random()""" 

arcpy.MakeFeatureLayer_management(fc, "TEST_ORIENT_LAYER", fieldName + " = 0")

arcpy.CalculateField_management("TEST_ORIENT_LAYER", fieldName, expression, "PYTHON_9.3", codeblock)

Using make feature layer makes an "in memory" pointer to the layer, much like adding the layer to an MXD does, it also happens to allow you to set a where clause.  Once you have this (I called it TEST_ORIENT_LAYER) then you can access it in almost any toolbox, as almost all of them take in a Feature Layer or a Feature Class (shape files included).  Check out the documentation here:

ArcGIS Help 10.1

As an aside, in my testing, until you want to calculate more than about 5 columns per row, it is faster to use a method like this as the Calc Field tool is faster than even a Data Access cursor until about 5 columns.  After 5 columns, you should probably open the cursor and do the calculations yourself.

View solution in original post

0 Kudos
3 Replies
ChristopherMoravec1
New Contributor II

Ben,

It might be easier in this case (and probably faster) to simply us a feature layer and your calculate field.  I would try something like this:

import arcpy

fc = r"c:\Test_Orient.shp" 

feildName = "ORIENT" 

expression = "rand_num()*360" 

codeblock = """def rand_num():

    import random

    return random.random()""" 

arcpy.MakeFeatureLayer_management(fc, "TEST_ORIENT_LAYER", fieldName + " = 0")

arcpy.CalculateField_management("TEST_ORIENT_LAYER", fieldName, expression, "PYTHON_9.3", codeblock)

Using make feature layer makes an "in memory" pointer to the layer, much like adding the layer to an MXD does, it also happens to allow you to set a where clause.  Once you have this (I called it TEST_ORIENT_LAYER) then you can access it in almost any toolbox, as almost all of them take in a Feature Layer or a Feature Class (shape files included).  Check out the documentation here:

ArcGIS Help 10.1

As an aside, in my testing, until you want to calculate more than about 5 columns per row, it is faster to use a method like this as the Calc Field tool is faster than even a Data Access cursor until about 5 columns.  After 5 columns, you should probably open the cursor and do the calculations yourself.

0 Kudos
BenLeslie1
Regular Contributor

This one works for me.

Thanks John for your answer - looks pretty straight forward too - I will test it later as a learning exercise.

Cheers

0 Kudos
JohnFell
Occasional Contributor III

Ben,

Rather than calculate the row you will benefit from generating an updateCursor object rather than using the CalculateField gp tool. I believe the data access module (arcpy.da) is more efficient. You can check out the links here, here and here for more information.

Import arcpy, random

from arcpy import da

fc = r"c:\Test_Orient.shp"

fieldName = "ORIENT"

whereClause = fieldName + " = 0"

# create update cursor

urows = arcpy.da.updateCursor(fc, whereClause)

for urow in urows:

    urow.setValue(fieldName, row.getValue(random.random() * 360)

    urows.updateRow(urow)