{"id":2949,"date":"2021-05-03T14:37:55","date_gmt":"2021-05-03T02:37:55","guid":{"rendered":"http:\/\/blogs.lincoln.ac.nz\/gis\/?p=2949"},"modified":"2023-05-07T03:05:44","modified_gmt":"2023-05-07T03:05:44","slug":"deleting-smokers-closing-the-loops","status":"publish","type":"post","link":"https:\/\/blogs.lincoln.ac.nz\/gis\/deleting-smokers-closing-the-loops\/","title":{"rendered":"Deleting Smokers &#8211; Closing the Loop(s)"},"content":{"rendered":"<p><em>The last of our series on developing a Python script for some smoking reduction analysis.<\/em><\/p>\n<p>Long term readers of the GIS Blog (Hi Mum!) may recall a series of posts on the development of a Python script for some analysis.\u00a0 As part of the smoking reduction analysis I&#8217;ve been involved with over the years, we wanted to look at the impacts on accessibility to tobacco from imposing some distance limits on tobacco retailers.\u00a0 In other words, how would setting a minimum distance between retailers affect how easy it is to buy tobacco?\u00a0 After a survey of the literature, we settled on three distances to evaluate: 450 m, 300 m and 150 m.\u00a0 The previous posts set up the <a href=\"http:\/\/blogs.lincoln.ac.nz\/gis\/deleting-smokers-part-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">background<\/a>, tweaking some <a href=\"http:\/\/blogs.lincoln.ac.nz\/gis\/deleting-smokers-part-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">psuedo-code<\/a> and developing one of the key <a href=\"http:\/\/blogs.lincoln.ac.nz\/gis\/deleting-smokers-part-3-progress\/\" target=\"_blank\" rel=\"noopener noreferrer\">data preparation<\/a> scripts.\u00a0 In this post, we put this script to bed (or rather, get it out of bed and running!) and get some results.<\/p>\n<div class=\"tenor-gif-embed\"><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/I_m-Out-Of-Bed-by-Banksy-Art-Print-White-Frame-GW_0c8c1e43-5ec8-4752-aa65-cb83b5ee6a20.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2976\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/I_m-Out-Of-Bed-by-Banksy-Art-Print-White-Frame-GW_0c8c1e43-5ec8-4752-aa65-cb83b5ee6a20.jpg\" alt=\"\" width=\"1489\" height=\"1200\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/I_m-Out-Of-Bed-by-Banksy-Art-Print-White-Frame-GW_0c8c1e43-5ec8-4752-aa65-cb83b5ee6a20.jpg 1489w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/I_m-Out-Of-Bed-by-Banksy-Art-Print-White-Frame-GW_0c8c1e43-5ec8-4752-aa65-cb83b5ee6a20-300x242.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/I_m-Out-Of-Bed-by-Banksy-Art-Print-White-Frame-GW_0c8c1e43-5ec8-4752-aa65-cb83b5ee6a20-1024x825.jpg 1024w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/I_m-Out-Of-Bed-by-Banksy-Art-Print-White-Frame-GW_0c8c1e43-5ec8-4752-aa65-cb83b5ee6a20-768x619.jpg 768w\" sizes=\"auto, (max-width: 1489px) 100vw, 1489px\" \/><\/a><\/div>\n<p>So as a quick recap, we needed a script that would look at the 5,131 existing tobacco retailer points we&#8217;ve got in our existing database, figure out out close they all are to each other and then sequentially go through each, defining which ones are within a given minimum distance and then randomly delete one of them, and then keep doing this until none of the retailers is within that minimum distance.\u00a0 <em>And then<\/em>, do it all over again 1,000 times so we end up with a 1,000 iterations of this &#8211; giving us an ensemble of possible configurations.\u00a0 The random deletion means that everyone could be different and we have a massive dataset to do some more general statistics on.<\/p>\n<p>Well I&#8217;m very pleased to say that we&#8217;ve brought this all to fruition, though with 100 iterations rather than 1,000.\u00a0 In this post I&#8217;ll try to highlight the key parts of this script without getting too bogged down in the details (<em>Ed.: a tall order<\/em>).<\/p>\n<p>In one of those earlier posts we saw the first data preparation script to find the proximity relationships between pairs of points.\u00a0 With those, it&#8217;s then a matter of going through each pair and randomly deleting one of the two.\u00a0 The tricky bit is going through the whole data set once, randomly deleting a point in a pair, but then doing it over and over again until none remain within that set distance.\u00a0 This immediately suggests loops that continue until a certain condition is met.\u00a0 The Near tool has been a critical tool in this script as it not only allows us to calculate the straight-line distance to the nearest retailer, but also allows us to limit how far away to look.\u00a0 So if our minimum distance is 450 m, any retailer with no other retailer within 450 m will be assigned a -1.\u00a0 When <strong>all<\/strong> the retailers get a NEARDIST value of -1, then that iteration is done and the script can start all over on a new sequence.\u00a0 So overall, we&#8217;ve got three main loops to this script:<\/p>\n<ul>\n<li>Inner loop: go through each proximity pair and delete one retailer at random<\/li>\n<li>Middle loop: continue inner loop until all retailers have a NEARDIST = -1<\/li>\n<li>Outer loop: Run the middle loop 100 times<\/li>\n<\/ul>\n<p>So it sort of looks something like this:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/loops2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2971\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/loops2.jpg\" alt=\"\" width=\"446\" height=\"468\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/loops2.jpg 446w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/05\/loops2-286x300.jpg 286w\" sizes=\"auto, (max-width: 446px) 100vw, 446px\" \/><\/a><\/p>\n<p>The middle loop controls the inner loop and tells it when to stop, while the outer loop runs the middle loop a set number of times.\u00a0 Let&#8217;s have a quick look at the individual loops that control this beast.<\/p>\n<p>We start with some comments on the script to help others understand what&#8217;s going on:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Comments.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2953\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Comments.jpg\" alt=\"\" width=\"1417\" height=\"539\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Comments.jpg 1417w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Comments-300x114.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Comments-1024x390.jpg 1024w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Comments-768x292.jpg 768w\" sizes=\"auto, (max-width: 1417px) 100vw, 1417px\" \/><\/a><\/p>\n<p>Then some preliminaries: importing Python libraries, and setting up some variables (Note: this version is using a 150 m distance):<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Prelim.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2954\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Prelim.jpg\" alt=\"\" width=\"782\" height=\"526\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Prelim.jpg 782w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Prelim-300x202.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Prelim-768x517.jpg 768w\" sizes=\"auto, (max-width: 782px) 100vw, 782px\" \/><\/a>(I haven&#8217;t cleaned up all my comments, those lines starting with &#8220;#&#8221; &#8211; these are mostly early tries at making something work.) &#8220;nearDist&#8221; is the variable that holds the minimum distance between retailers, &#8220;fields&#8221; lists the main attribute fields some of the tools will be using and &#8220;startLayer&#8221;\u00a0is used to give a base name to all the output layers.<\/p>\n<p>The outer loop then runs the show &#8211; it&#8217;s fairly simple:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/outer2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2956\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/outer2.jpg\" alt=\"\" width=\"897\" height=\"265\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/outer2.jpg 897w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/outer2-300x89.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/outer2-768x227.jpg 768w\" sizes=\"auto, (max-width: 897px) 100vw, 897px\" \/><\/a><\/p>\n<p>Here, a <a href=\"https:\/\/wiki.python.org\/moin\/ForLoop\" target=\"_blank\" rel=\"noopener noreferrer\">For loop<\/a> is implemented to run the code within it a set number of times. &#8220;i&#8221; is a counter that gets incremented every time the loop runs.\u00a0 Counting starts at 0 with Python and the 101 is the maximum number of times it&#8217;s to run, incrementing by 1 each time it runs.\u00a0 With this I actually get 101 iterations, since we start at 0 but stops when we get to 101.<\/p>\n<p>I use a Print statement just to let me check where in the process the script is, allowing me to keep an eye on progress.<\/p>\n<p>&#8220;copyOutput&#8221; is just a wee bit of text that I can tack on to the end of each layer&#8217;s base name (Full150) so I know which iteration it came from.\u00a0 The syntax means that each layer will be given a name Full150_i (where &#8220;i&#8221; of course changes with each iteration).\u00a0 You&#8217;ll see the effect of this later.<\/p>\n<p><a href=\"https:\/\/pro.arcgis.com\/en\/pro-app\/latest\/tool-reference\/data-management\/copy-features.htm\" target=\"_blank\" rel=\"noopener noreferrer\">CopyFeatures<\/a> creates a copy of the original dataset as a starting point with the name Full150_i<\/p>\n<p>Later on I&#8217;m going to be using Select by Attribute and, things being as they are, I need to create a Feature Layer to do this on.\u00a0 I&#8217;ve struggled for a long time to understand exactly what a Feature Layer is in this context and I think the best way to understand it is that it&#8217;s like a layer on a map &#8211; normally, Select by Attribute can only be used on a layer\u00a0 that&#8217;s on a map &#8211; this step is essentially adding a layer to a map, but it&#8217;s all virtual (<em>Ed.: Aren&#8217;t we all?<\/em>)<\/p>\n<p>Next, the middle loop comes into play:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/middle.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2957\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/middle.jpg\" alt=\"\" width=\"1019\" height=\"84\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/middle.jpg 1019w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/middle-300x25.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/middle-768x63.jpg 768w\" sizes=\"auto, (max-width: 1019px) 100vw, 1019px\" \/><\/a><\/p>\n<p>A simple but important line &#8211; it&#8217;s a <a href=\"https:\/\/wiki.python.org\/moin\/WhileLoop\" target=\"_blank\" rel=\"noopener noreferrer\">while loop<\/a>, meaning that it keeps running as long as the condition maxDist &gt; 0.0.\u00a0 As soon as that&#8217;s not true (i.e. maxDist = -1), the loop stops and returns control to the outer loop.\u00a0 What&#8217;s maxDist?\u00a0 We&#8217;ll see in more detail later, but for now, it&#8217;s the maximum distance as calculated by the Near tool, keeping in mind that we want things to stop when all the NEARDIST values = -1.<\/p>\n<p>From here we go into the inner loop, the guts of this script.\u00a0 In a nutshell, we iterate through each proximity pair (which has its own unique identifier), deleting one of the two at random.\u00a0 It&#8217;s quite long in here so I won&#8217;t show the whole thing, but it&#8217;s actually got a few sub-loops of its own.<\/p>\n<p>Since retailers have been deleted whenever this loop runs, I&#8217;ve got to use an <a href=\"http:\/\/blogs.lincoln.ac.nz\/gis\/deleting-smokers-part-3-progress\/\" target=\"_blank\" rel=\"noopener noreferrer\">earlier script<\/a> to create a unique ID (pairID) for each proximity pair at the beginning of every sweep.\u00a0 Since I&#8217;m making changes to the layer I first need to create an <a href=\"https:\/\/pro.arcgis.com\/en\/pro-app\/latest\/arcpy\/data-access\/updatecursor-class.htm\" target=\"_blank\" rel=\"noopener noreferrer\">update cursor<\/a>:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Update.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2958\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Update.jpg\" alt=\"\" width=\"1473\" height=\"128\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Update.jpg 1473w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Update-300x26.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Update-1024x89.jpg 1024w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Update-768x67.jpg 768w\" sizes=\"auto, (max-width: 1473px) 100vw, 1473px\" \/><\/a><\/p>\n<p>The cursor is primed to look at the fields in the current layer, set up at the beginning.\u00a0 The &#8220;paircounter&#8221; gives us a starting point for pairIDs.\u00a0 This next bit assigns the unique ID for each proximity pair features:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Pairid.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2959\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Pairid.jpg\" alt=\"\" width=\"1515\" height=\"448\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Pairid.jpg 1515w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Pairid-300x89.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Pairid-1024x303.jpg 1024w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Pairid-768x227.jpg 768w\" sizes=\"auto, (max-width: 1515px) 100vw, 1515px\" \/><\/a><\/p>\n<p>Note that the paircounter is incremented by 1 at the end of this loop so next time around the pairID is one unit larger.\u00a0 The loop continues until each row has been gone through.\u00a0 With the PairIDs in place another while loop allows us to iterate through each proximity pair. &#8220;dcount&#8221; gives us a place to start:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/dcount.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2960\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/dcount.jpg\" alt=\"\" width=\"1462\" height=\"303\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/dcount.jpg 1462w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/dcount-300x62.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/dcount-1024x212.jpg 1024w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/dcount-768x159.jpg 768w\" sizes=\"auto, (max-width: 1462px) 100vw, 1462px\" \/><\/a><\/p>\n<p>What&#8217;s with the 3712?\u00a0 This is the number of possible proximity pairs + 1 (determined from the base data layer before the script runs).\u00a0 This is just a way to limit the number of times the loop runs for efficiency.\u00a0 While dcount is less that 3712, the loop gets a set of values to chose from, 0 or 1 (the basis of our random deletion).\u00a0 &#8220;whereClause&#8221; is text that will be used in a Select by Attribute step &#8211; it translates to: select the records where PairID = dcount (again, dcount will change with each iteration in this loop).\u00a0 There&#8217;s a risk that I&#8217;ll select a dcount that only has one record and to ensure I work with dcount pairs, this next little bit does a quick count of selected records to make sure there are two.\u00a0 If so, it moves on to the next step (if not, it goes to the next value of dcount):<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/if2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2961\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/if2.jpg\" alt=\"\" width=\"1493\" height=\"272\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/if2.jpg 1493w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/if2-300x55.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/if2-1024x187.jpg 1024w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/if2-768x140.jpg 768w\" sizes=\"auto, (max-width: 1493px) 100vw, 1493px\" \/><\/a><\/p>\n<p>Now, we&#8217;re finally at the heart of this script &#8211; if there are two records in the selection, pick one at random and delete it:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/delete.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2962\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/delete.jpg\" alt=\"\" width=\"848\" height=\"534\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/delete.jpg 848w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/delete-300x189.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/delete-768x484.jpg 768w\" sizes=\"auto, (max-width: 848px) 100vw, 848px\" \/><\/a><\/p>\n<p>The &#8220;choice&#8221; line randomly selects either 0 or 1 and then one or the other of the two selected records is deleted.\u00a0 &#8220;dcount&#8221; increases by one and we move to the next pair.<\/p>\n<p>Pshew!\u00a0 Now it&#8217;s time to start digging ourselves from the bottom of these loops.\u00a0 This one continues until all the NEARDIST values are -1.\u00a0 Once there, the Near tool runs again to update the distances to the nearest retailers:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/NearRedo.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2963\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/NearRedo.jpg\" alt=\"\" width=\"994\" height=\"289\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/NearRedo.jpg 994w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/NearRedo-300x87.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/NearRedo-768x223.jpg 768w\" sizes=\"auto, (max-width: 994px) 100vw, 994px\" \/><\/a><\/p>\n<p>Before we leave here, all the PairID values are reset to -1 so on the next iteration they can be allocated a new PairID.\u00a0 This loop continues until all the NEARDIST values are -1.\u00a0 We then return to the outer loop and start it all over again.\u00a0 When i hits 101, the script exits and we get a most satisfying message on the Python console:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Done.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2964\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Done.jpg\" alt=\"\" width=\"761\" height=\"222\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Done.jpg 761w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Done-300x88.jpg 300w\" sizes=\"auto, (max-width: 761px) 100vw, 761px\" \/><\/a><\/p>\n<p>Can you imagine doing this all manually?\u00a0 I can&#8217;t.\u00a0 Wouldn&#8217;t dream of it.\u00a0 Wouldn&#8217;t pay anyone to do it either.<\/p>\n<p>A few notes.\u00a0 On my desktop machine, this took very close to a week of continuous running to fully execute.\u00a0 Once finished, a quick look at the Catalog shows the base layer and all the iterated output layers:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Catalog.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2965\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Catalog.jpg\" alt=\"\" width=\"967\" height=\"748\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Catalog.jpg 967w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Catalog-300x232.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Catalog-768x594.jpg 768w\" sizes=\"auto, (max-width: 967px) 100vw, 967px\" \/><\/a><\/p>\n<p>Full150 was the starting point with 5,131 retailers and all the other layers are the outputs from the script (remember that bit of script that added the underscore and the iteration count up at the beginning?).\u00a0 Around 1,820 retailers were deleted from each layer, but the locations of the ones remaining will differ from layer to layer due to the random deletions.<\/p>\n<p>So.\u00a0 What a long process to get here. My part is (mostly) done so one of my last steps is to get these results to my more statistically-minded colleagues (in the <em>nicest<\/em> possible way) for that end of the analysis.\u00a0 What would be useful for them is spreadsheets so my last step is to convert all the layers&#8217; attribute tables to Excel using the (aptly named) <a href=\"https:\/\/pro.arcgis.com\/en\/pro-app\/latest\/tool-reference\/conversion\/table-to-excel.htm\" target=\"_blank\" rel=\"noopener noreferrer\">Table to Excel <\/a>tool.\u00a0 Rather than sit in front of my machine and run this 101 times, I put a very quick <a href=\"http:\/\/blogs.lincoln.ac.nz\/gis\/flow-diagrams-that-work\/\" target=\"_blank\" rel=\"noopener noreferrer\">ModelBuilder <\/a>model together to do the hard (boring) work for me.\u00a0 At the last minute we realised that we needed the distances to the nearest retailer as well, so I simple added that in as a step (this is the 300 m version):<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/model.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2966\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/model.jpg\" alt=\"\" width=\"1311\" height=\"499\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/model.jpg 1311w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/model-300x114.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/model-1024x390.jpg 1024w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/model-768x292.jpg 768w\" sizes=\"auto, (max-width: 1311px) 100vw, 1311px\" \/><\/a><\/p>\n<p>A nice feature here is the <a href=\"https:\/\/pro.arcgis.com\/en\/pro-app\/latest\/tool-reference\/modelbuilder-toolbox\/iterate-feature-classes.htm\" target=\"_blank\" rel=\"noopener noreferrer\">Iterate Feature Classes<\/a> iterator.\u00a0 This lets me point at a geodatabase and it will run the subsequent tools on each layer present.\u00a0 Et voila!\u00a0 All of my layers are now spreadsheets which I share with my colleagues thorugh OneDrive:<\/p>\n<p><a href=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Sheets.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2967\" src=\"https:\/\/d-blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Sheets.jpg\" alt=\"\" width=\"1207\" height=\"753\" srcset=\"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Sheets.jpg 1207w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Sheets-300x187.jpg 300w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Sheets-1024x639.jpg 1024w, https:\/\/blogs.lincoln.ac.nz\/gis\/wp-content\/uploads\/sites\/3\/2021\/04\/Sheets-768x479.jpg 768w\" sizes=\"auto, (max-width: 1207px) 100vw, 1207px\" \/><\/a><\/p>\n<p>Nice.\u00a0 And that brings us to the end of this sordid tale.\u00a0 I&#8217;ve learned a lot along the way and would be the first to say that this script isn&#8217;t very elegant.\u00a0 I&#8217;m sure some of our MAC students would have some good suggestions on how to improve it.\u00a0 I&#8217;m open to suggestions!<\/p>\n<p>C<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The last of our series on developing a Python script for some smoking reduction analysis. Long term readers of the GIS Blog (Hi Mum!) may recall a series of posts on the development of a Python script for some analysis.\u00a0 As part of the smoking reduction analysis I&#8217;ve been involved with over the years, we [&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-2949","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/posts\/2949","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=2949"}],"version-history":[{"count":1,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/posts\/2949\/revisions"}],"predecessor-version":[{"id":4085,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/posts\/2949\/revisions\/4085"}],"wp:attachment":[{"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/media?parent=2949"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/categories?post=2949"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.lincoln.ac.nz\/gis\/wp-json\/wp\/v2\/tags?post=2949"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}