Learning Python to use in ArcGis 10.2.

I want to get value from a certain field from one attribute table into another attribute table. IN PT1, If Meas of Object1 > Meas of Object2, then in SPL1 End = Punkt_ID of Object1 and Start = Punkt_ID of Object2

Like this:

enter image description here

So I have written this bit (based on existing scripts) where individual segments are used to select points in order to update the Split_Lines attribute table

## Update field End with max value
OIDField = arcpy.Describe(SplitLines).OIDFieldName
Lines = arcpy.UpdateCursor(SplitLines)
for Line in Lines:
    LineId = OIDField
    Where_clause = '"' + OIDField + '"=' +str(LineId) 
    arcpy.MakeFeatureLayer_management (SplitLines, "Current_Line", Where_clause)
    arcpy.SelectLayerByLocation_management ("Points_Lyr","WITHIN_A_DISTANCE","Current_Line", "0.02 METERS")
    pcur = arcpy.SearchCursor("Points_Lyr")
    prow = pcur.next()
    p1val = prow.getValue("MEAS")
    p1HH = prow.getValue("HH")
    p1ID = prow.getValue("Punkt_ID")
    prow = pcur.next()
    p2val = prow.getValue("MEAS")
    p2HH = prow.getValue("HH")
    p2ID = prow.getValue("Punkt_ID")

if p2val > p1val:
    Line.setValue("End", p2ID)
    Line.setValue("Start", p1ID)
    Line.setValue("HH_Stromab", p1HH)
    Line.setValue("HH_Stromauf", p2HH)

    Line.setValue("End", p1ID)
    Line.setValue("Start", p2ID)
    Line.setValue("HH_Stromab", p2HH)
    Line.setValue("HH_Stromauf", p1HH)
del prow
del pcur 

I am almost there, only the Search Cursor on the Selected Points doesn't seem to update for each new selection and copy the Value of Punkt_ID =1 and Punkt_ID =2.

Like this: enter image description here

Where is the mistake?

  • 1
    You need to use an UpdateCursor to accomplish this. – crmackey Jan 14 '15 at 13:50
  • Did you split the lines at the points? If so, a spatial join followed by field calc's with a codeblock might work. – gm70560 Jan 14 '15 at 18:44
  • You should print your Where_clause. I don't think it returns what you think it should. It looks like it should return: "OID" = OID. Use this instead: LineId = Line.getValue(OIDField) – phloem Jan 14 '15 at 22:02
  • @crmackey, the update Cursor is applied on Lines (SplitLine). – PMessager Jan 15 '15 at 7:22
  • @gm70560, I did try that too, but the aim is to have a python script rather than a tool based on model builder – PMessager Jan 15 '15 at 7:24

I am posting the code which should fulfill your requirement (based on my understanding of your requirement).

# required import
import arcpy

# path of Points_lyr feature class/table (point)
point_fc = r'D:\Python\ScratchDatabase\Geodatabase.gdb\Point'

# related fields #first field 'MEAS' to compare and second field 'Punkt_ID' to assign
# as you are taking other fields too (seen in your code). you can add those like
# point_flds = ['MEAS', 'Punkt_ID', 'HH']
# and map them as
# line_flds = ['OID@','Start', 'End', 'HH_Stromab', 'HH_Stromauf']
point_flds = ['MEAS', 'Punkt_ID', 'HH']

# path of split_Lines feature class (Line)
line_fc = r'D:\Python\ScratchDatabase\Geodatabase.gdb\Line'

# line fields #first field to get OBJECTID of current line segment,
# second field 'Start' to assign start id (Punkt_ID) and
# third field 'End' to assign end id (Punkt_ID)
# you can add
line_flds = ['OID@','Start', 'End', 'HH_Stromab', 'HH_Stromauf']

# for search by location to find and select
point = arcpy.MakeFeatureLayer_management(point_fc)

# update the values of line feature class
with arcpy.da.UpdateCursor(line_fc, line_flds) as update_cursor:
    for row in update_cursor:
        # create where clause
        where = '"OBJECTID"={}'.format(row[0])

        # take one segment at a time
        line = arcpy.MakeFeatureLayer_management(line_fc, where_clause=where)

        # apply selection on point feature class
        # change the criteria accordingly to suit your problem in distance
        selection = arcpy.SelectLayerByLocation_management(point, 'WITHIN_A_DISTANCE', line, "0.02 METERS", "NEW_SELECTION")
        comp_list = []
        with arcpy.da.SearchCursor(selection, point_flds) as cursor:
            for search_row in cursor:
                # add all point which comes after select by location
        # sort on the basis of 'MEAS' value
        sort = sorted(comp_list, key= lambda x: x[0])
        # assign smallest 'MEAS' value 'Punkt_ID' to 'Start'
        row[1] = sort[0][1]
        # assign largest 'MEAS' value 'Punkt_ID' to 'End'
        row[2] = sort[-1][1]
        # assign 'HH' value to 'HH_Stromab' for smallest 'MEAS'
        row[3] = sort[0][2]
        # assign 'HH' value to 'HH_Stromauf' for largest 'MEAS'
        row[4] = sort[-1][2]
        # update the line row
  • This Looks like a very elegant solution and it worked well. Could you please explain what means "key= lambda x: x[0]"? I replace "line = arcpy.MakeFeatureLayer_management(line_fc, where_clause=where)" by "arcpy.MakeFeatureLayer_management(SplitLines,"current_line", where)" in order to not get multiple layers of single Segment. Many thanks! – PMessager Jan 15 '15 at 8:15
  • @PMessager: To understand key= lambda x: x[0]. Please check Python HowTo – Surya Jan 15 '15 at 10:38
  • @PMessager: both ways to make feature classes are same, it creates in_memory feature class. But, by using line = arcpy.MakeFeatureLayer_management(line_fc, where_clause=where), we can have more control on the feature class as you have it in line variable. But by this way arcpy.MakeFeatureLayer_management(SplitLines,"current_line", where). it may throw an error ExecuteError: Failed to execute. Parameters are not valid. ERROR 000725: Output Layer: Dataset current_line already exists. Failed to execute (MakeFeatureLayer). if you haven't set arcpy.env.overwriteOutput = True – Surya Jan 15 '15 at 11:08
  • arcpy.env.overwriteOutput = True is implemented. Now I am trying to get out of the hardcoding to set the script as a tool... – PMessager Jan 15 '15 at 12:13

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.