{"id":2697,"date":"2020-10-08T15:29:01","date_gmt":"2020-10-08T02:29:01","guid":{"rendered":"http:\/\/blogs.lincoln.ac.nz\/gis\/?p=2697"},"modified":"2023-05-07T03:12:33","modified_gmt":"2023-05-07T03:12:33","slug":"deleting-smokers-part-3-progress","status":"publish","type":"post","link":"https:\/\/blogs.lincoln.ac.nz\/gis\/deleting-smokers-part-3-progress\/","title":{"rendered":"Deleting Smokers &#8211; Part 3 &#8211; Progress!"},"content":{"rendered":"<p><em>In Part 3 of a series on developing a Python script, some progress is detailed.\u00a0 A short data-massaging script helps prepare the input data for the main script.<\/em><\/p>\n<p>In this ongoing series about developing a Python script for some analysis, we first covered what <a href=\"http:\/\/blogs.lincoln.ac.nz\/gis\\\/deleting-smokers-part-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">the script needs to do<\/a>\u00a0and then also covered some <a href=\"http:\/\/blogs.lincoln.ac.nz\/gis\/deleting-smokers-part-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">data issues<\/a>.\u00a0 After several full on days of banging my head against a digital wall, I think I&#8217;ve made a bit of progress!\u00a0 Recall that we&#8217;re looking at some analysis that looks at reducing the number of tobacco retailers based on a minimum distance criterion (i.e., there should be no tobacco retailers within a given distance of another retailer).\u00a0 The trick is in systematically removing retailers in a defensible and logical way.<\/p>\n<p>At the end of our last post, I had the input data down to three options for setting up the proximity relationship: a point layer of retailers that the Near tool has been run on (thus providing distances from each point to the nearest retailer), a similar output from the Generate Near Table tool that is a table rather than a point layer, and the output from an OD Cost Matrix.\u00a0 To be honest, at the start of this I though the cost matrix would be the way to go, but after last week, I think it&#8217;s a bit more problematic than it&#8217;s worth.<\/p>\n<p>So I&#8217;ve decided to focus on the point layer with the near distances in the table.\u00a0 Some benefits of this are that I&#8217;m working directly with the points that will need to be deleted, cutting down on any extra to-ing an fro-ing between other layers or tables.\u00a0 Also, the Near tool allows me to limit the distances that are calculated so I&#8217;ll easily be able to know which didn&#8217;t have a retailer within that minimum distance (I should be able to do this with the OD Cost Matrix but I haven&#8217;t been able to make that work yet).\u00a0 One downside is that I&#8217;ll be working with as-the-crow-flies straight line distances rather than distances along the road network (which would be more realistic but at these distances might not make much difference).<\/p>\n<p>So, here&#8217;s what my input data table looks like after running the Near tool:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/NearPoints1.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2698\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/NearPoints1.jpg\" alt=\"\" width=\"296\" height=\"372\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/NearPoints1.jpg 296w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/NearPoints1-239x300.jpg 239w\" sizes=\"auto, (max-width: 296px) 100vw, 296px\" \/><\/a><\/p>\n<p>Each point has an OBJECTID, a unique identifier that Pro uses to keep track of each point.\u00a0 The NEAR_FID is the OBJECTID of the nearest point and NEAR_DIST is the straight line distance between the two.\u00a0 So the point with OBJECTID = 1 is 143.898713 metres away\u00a0from the point with\u00a0NEAR_FID = 274, for example.\u00a0 When running this tool, I set the search distance to 500 m, meaning that if it doesn&#8217;t find another point within that distance, it will return a value of -1 for both NEAR_FID and NEAR_DIST.\u00a0 You can see two examples of that in the table above.<\/p>\n<p>In the last post I was rattling on about reciprocals and needing to link them.\u00a0 Here&#8217;s what I mean &#8211; if I sort the table by NEAR_DIST and scroll down past all the -1s, you can see that for every OBJECTID\/NEAR_FID distance, there&#8217;s its opposite (reciprocal), where the OBJECTID and NEAR_FID are swapped:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/NearPoints2a.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2700\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/NearPoints2a.jpg\" alt=\"\" width=\"308\" height=\"387\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/NearPoints2a.jpg 308w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/NearPoints2a-239x300.jpg 239w\" sizes=\"auto, (max-width: 308px) 100vw, 308px\" \/><\/a><\/p>\n<p>I&#8217;ve highlighted one pair to illustrate &#8211; each point is listed separately but they have the same distance.\u00a0 This is a good thing as this is the proximity relationship between these two points.\u00a0 Later in the script I&#8217;ll need to delete one of these &#8211; but first I need to know which points are these de facto relationships.<\/p>\n<p><em>(While we&#8217;re here, notice that there are some points that don&#8217;t have reciprocals &#8211; at first these were keeping me awake at night but I&#8217;m now a lot less worried about them.\u00a0 More on these later.)<\/em><\/p>\n<p>Okay &#8211; so while this allows me to know the proximity relationships, it&#8217;s a bit too complicated at this stage to work with these, so I&#8217;m wanting to do a bit of data massaging, for which I&#8217;ll use a wee script to identify those points that have reciprocals and assign them a unique id &#8211; I can then later use\u00a0this in the main script as my proximity relationship identifier (did that statement make any sense at all?\u00a0 (<em>Ed. no, not really, but carry on&#8230;<\/em>)<\/p>\n<p>Naively, I thought I&#8217;ll just whip up this script in a few minutes and move on.\u00a0 That&#8217;s when the banging me head up against a digital wall started &#8211; and boy, does my aura hurt.<\/p>\n<p>Here&#8217;s the guts of what I wanted to script to do (psuedo-code):<\/p>\n<ul>\n<li>With the points sorted by ascending OBJECTID, go through each point and pull out the NEAR_FID<\/li>\n<li>Search though all the other points to find a point where the OBJECTID and the NEAR_FID are reversed (I could do this by finding another point where NEAR_DIST is the same but there is a very slim (<em>veeeeery slim<\/em>) chance that there might be more than one).<\/li>\n<li>Give both of those points\u00a0the same\u00a0unique identifier<\/li>\n<li>If NEAR_DIST = -1, leave the point alone<\/li>\n<li>If there is no reciprocal, leave the point alone.<\/li>\n<\/ul>\n<p>In theory this sound like it should be pretty straightforward.\u00a0 To make this work, I&#8217;ll add a new attribute to my point layer, called PairID and initially populate it with values of 0.\u00a0 Then I&#8217;ll do a quick Select by Attribute on records where NEAR_DIST = -1 and reset their PairID to -1 (I want to test that the script correctly leaves those records alone):<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/WithPairID.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2703\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/WithPairID.jpg\" alt=\"\" width=\"345\" height=\"440\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/WithPairID.jpg 345w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/WithPairID-235x300.jpg 235w\" sizes=\"auto, (max-width: 345px) 100vw, 345px\" \/><\/a><\/p>\n<p>Now for the script.\u00a0 I won&#8217;t go into excruciating detail here, just the main points\u00a0(<em>Ed. pshew!<\/em>).\u00a0 \u00a0At the top of the script, I&#8217;ve set up a counter that allows me to iterate through all the records and a list that holds the names of the field in my attribute table:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script1.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2704\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script1.jpg\" alt=\"\" width=\"416\" height=\"48\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script1.jpg 416w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script1-300x35.jpg 300w\" sizes=\"auto, (max-width: 416px) 100vw, 416px\" \/><\/a><\/p>\n<p>Next, since I&#8217;m wanting to change attribute values, I&#8217;m going to use a thing called an <a href=\"https:\/\/pro.arcgis.com\/en\/pro-app\/arcpy\/data-access\/updatecursor-class.htm\" target=\"_blank\" rel=\"noopener noreferrer\">UpdateCursor<\/a> that&#8217;s specifically designed to work in loops and make changes to tables.\u00a0 The layer I&#8217;m working with is called &#8220;<span style=\"color: #008080\">points<\/span>&#8221; inside the script &#8211; this next line creates the UpdateCursor:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2705\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script2.jpg\" alt=\"\" width=\"510\" height=\"25\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script2.jpg 510w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script2-300x15.jpg 300w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/a><\/p>\n<p>I next need a\u00a0 <span style=\"color: #3366ff\">for<\/span>\u00a0loop, the guts of which are below:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script3.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2706\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script3.jpg\" alt=\"\" width=\"833\" height=\"274\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script3.jpg 833w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script3-300x99.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Script3-768x253.jpg 768w\" sizes=\"auto, (max-width: 833px) 100vw, 833px\" \/><\/a><\/p>\n<p>Allow me to (try to) translate &#8211;\u00a0\u00a0the &#8220;<span style=\"color: #3366ff\">for<\/span>&#8221; signals that I&#8217;m going to loop through each row (record) in the <span style=\"color: #008080\">points<\/span> table and do something.<\/p>\n<p>The &#8220;<span style=\"color: #3366ff\">if<\/span>&#8221; line is a conditional statement; if the comparison that follows is true, do something, if it&#8217;s not, then don&#8217;t do anything.\u00a0 Since Python starts counting at 0, &#8220;row[<span style=\"color: #3366ff\">2<\/span>]&#8221; is a way to access the attribute value in the <em>third<\/em> field, which happens to be <span style=\"color: #008080\">PairID<\/span>.\u00a0 If that value is NOT equal to 0, do nothing, but if it is, execute the next line.<\/p>\n<p>The next line, &#8220;row[<span style=\"color: #3366ff\">2<\/span>] = count&#8221; assigns the current value of count to the PairID and the line afterwards, &#8220;cursor.updateRow(row)&#8221; writes that value to the table.<\/p>\n<p>Note the differences between what &#8220;==&#8221; and &#8220;=&#8221; mean &#8211; the former is a comparison, the latter assigns a value.\u00a0 Anyway, I&#8217;ve just reset the value of <span style=\"color: #008080\">PairID<\/span> to make it the same as the value of the count variable.\u00a0 (Why?\u00a0 We&#8217;ll see why later.)<\/p>\n<p>The next two lines assign the value of <span style=\"color: #008080\">OBJECTID<\/span> to a new variable called &#8220;oid&#8221; and the value of <span style=\"color: #008080\">NEAR_ID <\/span>to the new variable &#8220;near&#8221; <em>for this record<\/em>.<\/p>\n<p>The &#8220;print()&#8221; statement is a useful way of keeping track of where the script is and if it&#8217;s working properly &#8211; they&#8217;re great for on-the-fly debugging and I tend to make extensive use of them.\u00a0 This line just prints out the value of these new variables.<\/p>\n<p>So all I&#8217;ve done so far is to start with the first record, reset its <span style=\"color: #008080\">PairID<\/span> to count and grabbed its <span style=\"color: #008080\">OBJECTID<\/span> and <span style=\"color: #008080\">NEAR_FIDs<\/span>.\u00a0 I next need to find its reciprocal (if there is one).\u00a0 I&#8217;m going to do this with with a Select by Attribute that looks for a record where OBJECTID = near and NEAR_FID = oid (by just swapping their values).\u00a0 Good practice when using something like Select by Attribute is to write the text for the query on a separate line, as the &#8220;whereClause&#8221;.\u00a0 It might look a little odd and I&#8217;ll show it again:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/where.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2707\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/where.jpg\" alt=\"\" width=\"585\" height=\"24\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/where.jpg 585w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/where-300x12.jpg 300w\" sizes=\"auto, (max-width: 585px) 100vw, 585px\" \/><\/a><\/p>\n<p>The &#8220;<strong><span style=\"color: #008080\">&#8220;&#8221;&#8221;<\/span><\/strong>&#8221; (try that at home) is Python&#8217;s way of saying what&#8217;s inside the triple quotes is all text.\u00a0 The use of <span style=\"color: #008080\">{}<\/span> instead of text is a way that I can pass in variable values so that the whereClause is actually different every time it loops.\u00a0 the &#8220;.format(near,oid)&#8221; just means that for the first set of {}s insert the value of near and for the second use the value of oid.<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/SbA.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2708\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/SbA.jpg\" alt=\"\" width=\"647\" height=\"44\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/SbA.jpg 647w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/SbA-300x20.jpg 300w\" sizes=\"auto, (max-width: 647px) 100vw, 647px\" \/><\/a><\/p>\n<p>These lines do the selection (there should only be one record that gets selected at most) and the resets the value of the <span style=\"color: #008080\">PairID<\/span> attribute to count &#8211; now both these records have the same <span style=\"color: #008080\">PairID<\/span> &#8211; thus their proximity relationship.<\/p>\n<p>Next,\u00a0<a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/count.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2709\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/count.jpg\" alt=\"\" width=\"153\" height=\"27\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/count.jpg 153w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/count-150x27.jpg 150w\" sizes=\"auto, (max-width: 153px) 100vw, 153px\" \/><\/a>, increments the value of count by 1.\u00a0 <a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/print.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2710\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/print.jpg\" alt=\"\" width=\"147\" height=\"24\" \/><\/a>\u00a0lets me know for sure that this has happened so I can follow the progress.<\/p>\n<p>This is the last line of the <span style=\"color: #3366ff\">for<\/span> loop so the script now goes back to the top of the loop and does\u00a0all those steps to\u00a0the next row, this time with count being equal to 2.\u00a0 It will continue this until <span style=\"color: #3366ff\">if<\/span> row[<span style=\"color: #3366ff\">2<\/span>] == <span style=\"color: #3366ff\">0\u00a0<span style=\"color: #000000\">is no longer true.\u00a0 Then it pops out of the loop and does t<\/span><\/span>he last few lines:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Finish.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2711\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Finish.jpg\" alt=\"\" width=\"633\" height=\"87\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Finish.jpg 633w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Finish-300x41.jpg 300w\" sizes=\"auto, (max-width: 633px) 100vw, 633px\" \/><\/a><\/p>\n<p>ensure that the selected record gets cleared and copies the resulting layer to a new layer, here called &#8220;TestPoints2018copy&#8221;\u00a0 The last thing the script does is print out &#8220;Done&#8221; so I know it&#8217;s finished.<\/p>\n<p>In the end, here&#8217;s the resulting table, sorted by PairID:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Done.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2712\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Done.jpg\" alt=\"\" width=\"400\" height=\"525\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Done.jpg 400w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/Done-229x300.jpg 229w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/a><\/p>\n<p>I struggle to see how I could do this manually without having to go through every single point &#8211; a mind-numbing prospect that would be quite prone to me making mistakes.\u00a0 I would also struggle to see how I could do this with <a href=\"http:\/\/blogs.lincoln.ac.nz\/gis\/flow-diagrams-that-work\/\" target=\"_blank\" rel=\"noopener noreferrer\">ModelBuilder<\/a>.<\/p>\n<p>To tidy things up, notice the PairID 5 has only one record.\u00a0 Why is this?\u00a0 Recall that the I limited the search distance that the Near tool used to 500 m.\u00a0 There might be some cases (such as PairID = 5) where\u00a0the nearest point is within 500 m <em>BUT<\/em> that other point has another point that is closer than PairID 5.\u00a0 That make sense?\u00a0 Probably not, so here&#8217;s a picture to illustrate:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/5b.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2716\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/5b.jpg\" alt=\"\" width=\"1405\" height=\"855\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/5b.jpg 1405w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/5b-300x183.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/5b-1024x623.jpg 1024w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2020\/10\/5b-768x467.jpg 768w\" sizes=\"auto, (max-width: 1405px) 100vw, 1405px\" \/><\/a><\/p>\n<p>The points are labelled with their OBJECTID.\u00a0 Points 65 and 66 are in a proximity relationship &#8211; each is the closest point\u00a0 to the other one.\u00a0 The closest point to 7 is 65, but since\u00a065 is physically closer to 66, point 7 doesn&#8217;t have a reciprocal.\u00a0 This is okay, but I do need to think about how I&#8217;m going to handle this in the next stages of the process (I think I have a plan for that).<\/p>\n<p>What this data-massaging allows me to do is to clearly model the proximity relationships.\u00a0 As a next step, I&#8217;ll work out how to cycle through each of the PairIDs and randomly delete one of the two points, then rerun Near, then redo this whole thing until I end up with just -1s for the NEAR_ID.\u00a0 Then I&#8217;ll know that there are no points within 500 m of another point.\u00a0 That will (hopefully) be the subject of the next, thrilling instalment.<\/p>\n<p>Reflecting on this script, it feels a bit clumsy to me &#8211; using both an UpdateCursor and Select by Attribute when I feel like I should just be able to do it with one UpdateCursor.\u00a0 I haven&#8217;t found a way to add a new row to the already selected row yet &#8211; I&#8217;m sure many au fait scripters out there will look at this and scoff, so I&#8217;m open to suggestions on how to do it better.<\/p>\n<p>The last thing I&#8217;ll say on this relates by banging my head against a digital wall &#8211; this was mainly around getting the format for the whereClause right.\u00a0 I tried for several days, all sorts of iterations and nothing seemed to work.\u00a0 Then I realised that it was probably because I was trying to run this script as a stand alone script, outside of Pro.\u00a0 In theory, I could run this anytime, with or without Pro open, but the reality was that for this script, and one line in particular (the Select by Attribute one), it needed to be run from inside Pro.\u00a0 Selection is a dynamic thing that only really exists inside a project, so while the script ran, it was never actually selecting anything until I copied and pasted the whole script into Pro (the Python window, to be exact), hit enter, and then it ran pretty flawlessly first time.\u00a0 Oh, the humanity!<\/p>\n<p>If anyone reading this is still awake, contact me and the first five people get a free Moro bar (<em>Ed. you&#8217;re assuming there are more than five people reading this&#8230;let alone one&#8230;<\/em>).<\/p>\n<p>Now onto more scripting!<\/p>\n<p>C<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Part 3 of a series on developing a Python script, some progress is detailed.\u00a0 A short data-massaging script helps prepare the input data for the main script. In this ongoing series about developing a Python script for some analysis, we first covered what the script needs to do\u00a0and then also covered some data issues.\u00a0 [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2697","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/posts\/2697","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/comments?post=2697"}],"version-history":[{"count":1,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/posts\/2697\/revisions"}],"predecessor-version":[{"id":4093,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/posts\/2697\/revisions\/4093"}],"wp:attachment":[{"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/media?parent=2697"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/categories?post=2697"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/tags?post=2697"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}