|
POST
|
You did not have to create a new field. You just needed to send one field to the equation, since you no longer need two fields for your labels like you did before. Before your key value was [ParcelBlockCommunity], but you did not want that to appear in the label and wanted [ParcelNumber] instead. For your new code you only need [Ref_B] once, since it is both your key and your label value. Try the code below instead. The change to line 53 should address the Null value issue and I commented out the Count = 0 label code. I have added a section for all the variables you need to set in lines 3 and 7 through 10 to make the code easier to modify. You should not need to alter the code below those lines, unless you wanted to change the label to a new format. # Initialize a global dictionary for a related feature class/table
relateDict = {}
def FindLabel ( [Ref_B]):
# declare the dictionary global so it can be built once and used for all labels
global relateDict
# set user variables here
keyField = [Ref_B]
labelField = [Ref_B]
FC = r"D:\RelateLabeling\s.gdb\Buildings_T"
fieldList = ["Ref_B", "NAME"]
# only populate the dictionary if it has no keys
if len(relateDict) == 0:
# Provide the path to the relate feature class/table
relateFC = FC
# create a field list with the relate field first (Ref_B),
# followed by sort field(s) (Ref_B), then label field(s) (NAME)
relateFieldsList = fieldList
# process a da search cursor to transfer the data to the dictionary
with arcpy.da.SearchCursor(relateFC, relateFieldsList) as relateRows:
for relateRow in relateRows:
# store the key value in a variable so the relate value
# is only read from the row once, improving speed
relateKey = relateRow[0]
# if the relate key of the current row isn't found
# create the key and make it's value a list of a list of field values
if not relateKey in relateDict:
# [searchRow[1:]] is a list containing
# a list of the field values after the key.
relateDict[relateKey] = [relateRow[1:]]
else:
# if the relate key is already in the dictionary
# append the next list of field values to the
# existing list associated with the key
relateDict[relateKey].append(relateRow[1:])
# delete the cursor, and row to make sure all locks release
del relateRows, relateRow
# store the current label feature's relate key field value
# so that it is only read once, improving speed
labelKey = keyField
# start building a label expression.
# My label has a bold key value header in a larger font
expression = u'<FNT name="Times New Roman" size="14"><BOL>' + labelField +'</BOL></FNT>'
# determine if the label key is in the dictionary
if labelKey in relateDict:
# sort the list of the list of fields
sortedList = sorted(relateDict[labelKey])
# add a record count to the label header in bold regular font
# expression += u'\n<FNT name="Times New Roman" size="12"><BOL>NAME Count = {}</BOL></FNT>'.format(len(sortedList))
# process the sorted list
for fieldValues in sortedList:
# append related data to the label expression
# Skip the value if it is Null
if fieldValues[0] != None:
expression += u'\n' + fieldValues[0]
# clean up the list variables after completing the for loop
del sortedList, fieldValues
# else:
# expression += '\n<FNT name="Arial" size="12"><BOL>NAME Count = 0</BOL></FNT>'
# return the label expression to display
return expression
... View more
12-27-2016
10:36 AM
|
0
|
1
|
2688
|
|
POST
|
For Question 1 simply remove or comment out lines 52 and 53. # else:
# expression += '\n<FNT name="Arial" size="10"><BOL>Owner Count = 0</BOL></FNT>'
For your second question it looks like you have created you own code for relationships you did not give in your previous example. Therefore I do not know what field or relationship you are talking about in your second question. All I can say is that in general you would need to supply a new subroutine in the code that converts the table and field into a dictionary and process the relationship similar to the code I previously wrote. For the last question you did not show me which fields are null in the Buiding_T table or the code that you are using for this new relationship. I have to know what fields are null to identify why that is preventing the code from running for that feature. In general nulls are a special case that have to be trapped to avoid such problems, but at this point I don't have the information I need to trap them. I have already made the code as adaptable as I am going to, and from my perspective it is already simple to adapt to new situations for anyone with reasonable experience in Python. I do not plan to make it simpler.
... View more
12-27-2016
07:29 AM
|
0
|
3
|
2688
|
|
BLOG
|
Please post your script code so I can test it. It is impossible to tell whether the code in my tool is at fault or the batch code you have written is at fault for this error without knowing the code you were using. Are you certain that the Amsterdam.shp input is the actual name of your layer and that the layer is a point shapefile and not a multi-point or some other shape type shapefile?
... View more
12-23-2016
10:34 AM
|
0
|
0
|
12969
|
|
POST
|
Kevin: I have not experienced a problem using the tool with 10.3.1 since I updated the file. I tried the tool just now in response to your post and the dockable window opened fine, recognized layers with M values fine and performed an update fine. To be sure I attached the correct add-in file I have deleted and reposted the add-in to my post above with a new date time of 12/13/16 at 12:17 PM. Do you have any other extensions running, especially editor extensions? My system has Attribute Assistant installed and that did not cause any issue for my tool, but other editor extensions might. Be sure to uninstall any prior version of the Add-In before installing the new one. Anyway, please relate the installation process you used if your problem persists. Also open Task Manager and report any unusual memory use or performance behaviors shown during the time the application crashes.
... View more
12-13-2016
12:28 PM
|
0
|
0
|
914
|
|
BLOG
|
Christopher: Thanks for taking the time to share your appreciation for this technique. The examples in this Blog are intentionally kept simple to emphasize the essentials of the technique. For a more advanced example of how the technique can be applied check out the code I developed in response to arcpy - How to improve performance of nested search cursors? - Geographic Information Systems Stack Exchange. The code in that post demonstrates: 1) how to use dictionaries when you are working with a set of tables that form a multilevel relational tree, 2) how to use the dictionary(list) method to efficiently populate a dictionary key with a list of lists dictionary value that will hold multiple data records associated with the key, 3) how to access the list of lists values when processing the dictionary keys for matches, and 4) how to create and use a tuple that will act as a multi-field composite dictionary key.
... View more
12-06-2016
02:49 PM
|
2
|
0
|
33947
|
|
POST
|
I realized that line 31 is necessary to avoid a memory leak when matching large sets of records and that it was invented wrong and so I restored that line and indented it one more level in my last post with code. Please use the revised code.
... View more
11-24-2016
09:18 AM
|
0
|
5
|
6047
|
|
POST
|
The code in my last post has been edited and is now fixed. The code will produce all labels now. Just use the code as it is now written. I had previously tried to fix the error, but the post did not save my edits. The error occurred because I had accidentally typed @ instead of # to comment out line 31.
... View more
11-23-2016
07:18 AM
|
2
|
7
|
6047
|
|
POST
|
First read my Blog post called Turbo Charging Data Manipulation with Python Cursors and Dictionaries. It covers this subject in much more depth with several examples of how to apply the technique and it provides code that is more standardized which should be easier to customize to your needs. As far as a Python dictionary it works like a real world dictionary. If you look up a word in a dictionary (a dictionary key) you will find all kinds of information related to that word (the value associated with the key). Python dictionaries offer is an extremely fast way to directly lookup related information through meaningful key values, as opposed to lists which only support a lookup using generally meaningless index number values or traversing the list in a loop. Python dictionary keys are not limited to words and can be nearly anything that is an immutable value. Tuples can be keys and can be used to create composite value keys (i.e., multi-field keys like the separate components of an address). Lists and Dictionaries are mutable and cannot be used as keys, but they can be values associated with a lookup key.
... View more
11-22-2016
02:57 PM
|
1
|
1
|
3452
|
|
POST
|
I am not sure what earlier e-mail you are referring to that contains links for downloading the routes and cities layers. I have scanned the posts in this thread and am unable to pick out any post that has provided such a link. If I have overlooked it please provide the date and time of the post. The reapportionment step is where the thread got confusing for me. I see no way to avoid a Python script for that step given the calibration requirements you have emphasized. However, using a Python script does not necessarily mess things up. In fact I would recommend writing a Python script to do the entire process so that it can be repeated easily in the future as the Urban boundaries and highway network continue to change. A well written Python script will document your process, provide a huge performance gain and can ultimately make that last update step as easy as pressing a button. Also in an earlier post you mentioned that you offset the rural segments from the urban segments by a distance of 0.001 miles to separate the ends of the polylines. However, that amount of offset translates to over 5 feet of separation, which would create a significant sink hole if that amount of pavement was to open up and separate in the real world. If you insist on applying an artificial offset to separate the end points of the lines I would recommend that you reexamine your resolution and tolerance settings and consider an offset value closer to the equivalent of a crack in the pavement, not a sink hole.
... View more
11-21-2016
12:32 PM
|
0
|
2
|
3028
|
|
POST
|
So to be clear, please separately confirm that you had no LRS routes based on postmiles already created prior to posting this issue. If that is the case, then I am assuming that the postmile values in your fields were measured/estimated by field staff relative to actual mile posts or by some other means that did not involved using LRS techniques and route calibration. Do you have any point layer for the actual mile posts positions that can be used for calibration in addition to the polyline end points? If such points exist between the end points of your lines they could alter the accuracy of the postmile distances interpolated between the line end points. Please let me know if the following example accurately describes what you want to accomplish. 1. Say I have a highway made up of 5 polyline segments with the following from and to postmiles. 0 to 2 2 to 5 5 to 8 8 to 12 12 to 19 2. If the urban boundaries intersected these segments at postmile positions 1 to 6 inclusive and 10 to 17 inclusive that would produce the following segments designated either Rural or Urban as follows: 0 to 1 Rural 1 to 2 Urban 2 to 5 Urban 5 to 6 Urban 6 to 8 Rural 8 to 10 Rural 10 to 12 Urban 12 to 17 Urban 17 to 19 Rural 3. If I ignore the Rural segments and just extract the 5 Urban segments I would create two new fields to hold the reapportionment of the Urban postmile measures. I would continue to use the first postmile measures of 1 to 6 for the first sets of 3 urban segments, but I would adjust the postmile measures of the second set of 2 urban segments to eliminate the postmile offset created by the gap separating it from the first set of urban segments. So taking just the 5 urban segments I would have a polyline with two fields showing the original postmile measures and two fields showing the reapportioned postmile measures as follows: 1 to 2 original urban and 1 to 2 reapportioned urban 2 to 5 original urban and 2 to 5 reapportioned urban 5 to 6 original urban and 5 to 6 reapportioned urban 10 to 12 original urban and 6 to 8 reapportioned urban 12 to 17 original urban and 8 to 13 reapportioned urban Total Urban postmiles = Beginning at original highway postmile 1 there are 12 Urban postmiles covered by these polylines (To postmile minus From postmile = postmile 13 - postmile 1 = 12 postmiles). If the above example is a correct presentation of what you want to do, this can be done using LRS techniques to obtain the postmile segments of section 2, but you would need a custom Python script to perform the steps needed to create the output shown in section 3.
... View more
11-21-2016
09:58 AM
|
0
|
1
|
3028
|
|
POST
|
I have commented out line 31 and line 43. Line 31 was indented wrong and causing it to interfere with the label generation beyond the first label, so I indebted it one more level (11/24/16 at 9:11 AM Pacific time). Line 43 creates a count that you apparently do not want, except where no owners exist I assume. Try this code: # Initialize a global dictionary for a related feature class/table
relateDict = {}
def FindLabel ( [ParcelBlockCommunity], [ParcelNumber] ):
# declare the dictionary global so it can be built once and used for all labels
global relateDict
# only populate the dictionary if it has no keys
if len(relateDict) == 0:
# Provide the path to the relate feature class/table
relateFC = r"C:\Users\main\Documents\ArcGIS\ValuatedParcels_Objection.gdb\Owners"
# create a field list with the relate field first (ParcelBlockCommunity),
# followed by sort field(s) (ParcelNumber), then label field(s) (OwnerName_Arabic)
relateFieldsList = ["ParcelBlockCommunity", "OwnerName_Arabic"]
# process a da search cursor to transfer the data to the dictionary
with arcpy.da.SearchCursor(relateFC, relateFieldsList) as relateRows:
for relateRow in relateRows:
# store the key value in a variable so the relate value
# is only read from the row once, improving speed
relateKey = relateRow[0]
# if the relate key of the current row isn't found
# create the key and make it's value a list of a list of field values
if not relateKey in relateDict:
# [searchRow[1:]] is a list containing
# a list of the field values after the key.
relateDict[relateKey] = [relateRow[1:]]
else:
# if the relate key is already in the dictionary
# append the next list of field values to the
# existing list associated with the key
relateDict[relateKey].append(relateRow[1:])
# delete the cursor, and row to make sure all locks release
del relateRows, relateRow
# store the current label feature's relate key field value
# so that it is only read once, improving speed
labelKey = [ParcelBlockCommunity]
# start building a label expression.
# My label has a bold key value header in a larger font
expression = u'<FNT name="Times New Roman" size="14"><BOL>' + [ParcelNumber] + '</BOL></FNT>'
# determine if the label key is in the dictionary
if labelKey in relateDict:
# sort the list of the list of fields
sortedList = sorted(relateDict[labelKey])
# add a record count to the label header in bold regular font
# expression += u'\n<FNT name="Times New Roman" size="10"><BOL>Owner Count = {}</BOL></FNT>'.format(len(sortedList))
# process the sorted list
for fieldValues in sortedList:
# append related data to the label expression
# my label shows a list of related
# cross streets and measures sorted in driving order
expression += u'\n' + fieldValues[0]
# clean up the list variables after completing the for loop
del sortedList, fieldValues
else:
expression += '\n<FNT name="Arial" size="10"><BOL>Owner Count = 0</BOL></FNT>'
# return the label expression to display
return expression This code separates each owner into its own line separated by a hard return. If you want more than one owner listed per line you will have to define the maximum number of characters you will allow per line and modify the loop at lines 45 to 49 to handle that format, but I am not prepared to suggest code that will accomplish that. You should request help with that in a separate post or on a Python forum.
... View more
11-21-2016
08:58 AM
|
1
|
0
|
13253
|
|
POST
|
I think I may be able to work out the solution, but I need to confirm some assumptions I have about the original data you have. I assume you have: 1. A polyline feature class/shapefile containing a set of polyline segments that make up a highway network. A. Each highway is made up of many polyline segments. B. Each polyline segment contains a field containing a highway ID value that can be used to select all of the polylines that make up a complete highway. C. Each polyline contains a pair of double fields listing the From and To postmile values for that polyline. D. The From field value is always lower than the To field value so that the postmile measures are always increasing. E. The orientation of the polyline geometry matches the orientation of the From and To postmile measures. F. The highways are generally using a single centerline to represent bidirectional travel rather than a dual centerline to represent each direction of travel separately. G. The polyline segments have had some topological validation to eliminate most dangles, self-intersections and overlaps where segments meet end to end. H. You are only concerned with postmile distances along highway through lanes and you can easily exclude highway ramps that may be in the network from this analysis. I. If any branching occurs you are willing to isolate and process these branches separately. This may happen at interchanges or along highway's that alternate between single centerlines and dual centerlines as the directions of travel alternately parallel and diverge from each other along a given route, 2. A polygon feature class/shapefile containing urban and rural boundaries. A. The polygons have been created separately from the highway network and/or there has been little or no topological control where the polygons and the polylines are supposed to represent the same boundary/centerline. B. The polygons have not been topologically validated and in all likelihood contain small slivers and gaps between boundaries that are supposed to be identical. (This only poses a concern along boundaries that follow highway centerlines for the purposes of this assignment). I am assuming you do not already have a LRS route network that actually has stored the calibrated postmile measure coordinates in the highway polyline geometry. If your polyline network actually stores measure coordinates in the polyline geometry that match the From and To measures of your fields that eliminates a large section of steps and is critical to know. Looking at your original post it appears you may have some kind of LRS routes with postmile measures already available, so it is crucial to know if that is the case and how it relates to the polyline segments you are trying to process. Almost every highway network has some geometry that does not follow the simple rules that only apply to simple routes that have non-repeating increasing measures. No program exists that can cover every possible real world highway configuration without some manual intervention. If you do not already have a validated LRS route network and are provided steps that work for more than 90% of your network, you will have to be satisfied with that. The law of diminishing returns sets in for the last 10% where it usually is less time consuming and more accurate to process it manually than it is to try to develop a programmatic approach, unless you are dealing with a massive data set at least 100 times larger than 2500 segments.
... View more
11-20-2016
07:33 PM
|
0
|
3
|
4176
|
|
POST
|
Your example does not answer my questions, because it is unfocused and you expect me to filter out the useless segments in the table view and reorder the segments in my mind to find the measure patterns you expect. That is not worth my time or anyone else's. Set the table view to only show selected records. Then using Iona Ave as an example, select only those segments that you are interested in on that route, i.e., select just the segments that you care about for a single measure pattern. I assume you would select the segments in just the urban areas, but I cannot be sure. Whatever you select should be sorted by the measure fields so I can determine what pattern your measures should follow. If the measures shown in the table are not the actual final measure values you really want/expect, create some new fields and write the actual values you expect or overwrite the values in the existing fields using a graphics program.
... View more
11-20-2016
05:38 PM
|
1
|
0
|
4176
|
|
POST
|
I am utterly confused by your illustrations and objections to the results you are getting, and do not think you have ever expressed your end objective clearly. Your expectations on what measures you think should be reported when gaps in the Urban events occurs is particularly confusing. Why should you want or expect the measures of separate urban areas to act like there is no gap when there is a gap in the full set of lines you used? To get what you want answer these questions. If the original set of lines has postmile 0 outside of the urban area, will the starting urban area postmile use whatever postmile it happens to fall at on the original complete route? Or does it need to create a new independent route that restarts at 0? Does the end postmile of the Urban route have to hold the measure that would have been reported on the original route for that end point? Or does it need to report a measure based only on the cumulative lengths that fall within the urban areas that are independent of the original measures? I.e., if two separate urban areas on the same route would originally measure 0 to 4 and 6 to 8 with measures 4 to 6 being rural, will the urban only measures that you want also be 0 to 4 and 6 to 8 or do you want them to report measures from 0 to 4 and 4 to 6 as though no rural segment existed between them? I think the best way to get step by step instructions would be for you to provide us with a shapefile of a complete set of polylines for a single highway that has several urban areas separated by rural areas along the full highway route and a shapefile of the urban and rural polygons that intersect that highway. That way we could all be working through the same data and compare the actual measure results each process produces to the measures that you would expect for that example
... View more
11-19-2016
06:49 AM
|
0
|
2
|
4176
|
|
POST
|
Your expression needs to add any field in the parcel data to the findLabel method and then you need to built the label with the fields you want displayed, so yes you must add fields to the code and change how the label is constructed to use the field you want. The screenshots you are providing are not enough for me to help you. You must show me the table view for the Parcels table showing me both the ParcelBlockCommunity field and ParcelNumber (also the separate fields for Block and Community would be nice to see as well) in the table at the same time. For the Owners table you need to show me both the ParcelBlockCommunity field and OwnerName_Arabic fields at the same time for the corresponding rows that match at least one of the parcels shown in the Parcel table screenshot. The parcel record that has matching owners in the tables should also be shown on the map. I have to be able to see the exact values that connect the two tables and that would be displayed in the label for an actual parcel and set of owners. Also, why is only one label shown on the map? Shouldn't the map be displaying labels for all of the parcels in the map view? How did you filter the label to only show parcel 32/53... It is important that you let me know, since I want to be sure it won't affect how the label expression behaves. I have revised the code based on the assumption that both tables have a field named ParcelBlockCommunity with identical values that match each parcel record to its corresponding owner records and that you want the label to display the ParcelNumber field and OwnerName_Arabic fields. To make the parcel unique don't you also need to display the Block value in the label? If you do, what is the name of the Block field? It would have to be added to line 3 and line 37. Let me know if any errors occur. # Initialize a global dictionary for a related feature class/table
relateDict = {}
def FindLabel ( [ParcelBlockCommunity], [ParcelNumber] ):
# declare the dictionary global so it can be built once and used for all labels
global relateDict
# only populate the dictionary if it has no keys
if len(relateDict) == 0:
# Provide the path to the relate feature class/table
relateFC = r"C:\Users\main\Documents\ArcGIS\ValuatedParcels_Objection.gdb\Owners"
# create a field list with the relate field first (ParcelBlockCommunity),
# followed by sort field(s) (ParcelNumber), then label field(s) (OwnerName_Arabic)
relateFieldsList = ["ParcelBlockCommunity", "OwnerName_Arabic"]
# process a da search cursor to transfer the data to the dictionary
with arcpy.da.SearchCursor(relateFC, relateFieldsList) as relateRows:
for relateRow in relateRows:
# store the key value in a variable so the relate value
# is only read from the row once, improving speed
relateKey = relateRow[0]
# if the relate key of the current row isn't found
# create the key and make it's value a list of a list of field values
if not relateKey in relateDict:
# [searchRow[1:]] is a list containing
# a list of the field values after the key.
relateDict[relateKey] = [relateRow[1:]]
else:
# if the relate key is already in the dictionary
# append the next list of field values to the
# existing list associated with the key
relateDict[relateKey].append(relateRow[1:])
# delete the cursor, and row to make sure all locks release
del relateRows, relateRow
# store the current label feature's relate key field value
# so that it is only read once, improving speed
labelKey = [ParcelBlockCommunity]
# start building a label expression.
# My label has a bold key value header in a larger font
expression = u'<FNT name="Times New Roman" size="14"><BOL>' + [ParcelNumber] + '</BOL></FNT>'
# determine if the label key is in the dictionary
if labelKey in relateDict:
# sort the list of the list of fields
sortedList = sorted(relateDict[labelKey])
# add a record count to the label header in bold regular font
expression += u'\n<FNT name="Times New Roman" size="10"><BOL>Owner Count = {}</BOL></FNT>'.format(len(sortedList))
# process the sorted list
for fieldValues in sortedList:
# append related data to the label expression
# my label shows a list of related
# cross streets and measures sorted in driving order
expression += u'\n' + fieldValues[0]
# clean up the list variables after completing the for loop
del sortedList, fieldValues
else:
expression += '\n<FNT name="Arial" size="10"><BOL>Owner Count = 0</BOL></FNT>'
# return the label expression to display
return expression
... View more
11-17-2016
07:44 AM
|
0
|
2
|
6047
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 03-24-2026 11:37 PM | |
| 1 | 03-24-2026 08:01 PM | |
| 6 | 02-23-2026 08:34 AM | |
| 1 | 03-31-2025 03:25 PM | |
| 1 | 03-28-2025 06:54 PM |
| Online Status |
Offline
|
| Date Last Visited |
a week ago
|