 Okay, so we're here to talk about lesson three. I have a number of slides that I'd like to talk through. And then I also have some exercises that we can walk through together. And so without further ado, let me get started. So a big part of lesson three is the topic of cursors. And I'm sorry, I'm trying to get out of this particular way of showing the slides. Can everybody see my slides? Okay. Yep, it's full screen now. Okay. All right, so the main topic of this lesson is cursors. And cursors is kind of an unusual term. We usually think of the thing on the screen, right, that blinks at you. But in this context, a cursor is used to manage a subset of tabular data. And there's three types of cursors that we can work with in ArcGIS, the search cursor, which is used really just to work with existing tabular data, not make any changes to the data. And then there's also the insert type used to add new data, add new records to a table. And there's the update cursor, which we can use to modify records. So we're going to focus mostly in this lecture here on search cursors. We'll talk about the other two as well. There's actually a few different alternatives, a few different search cursor classes built into ArcPy. And the one we're going to focus on here exclusively in this lecture, and you can read more about the other types in the lesson. But in this lecture, we're going to talk about the one that was introduced at ArcGIS 10.1 through the data access module, or so we get to that through the ArcPy.da module. And so that function is what we recommend. It offers the best performance functionality versus the other ones. You can find an older version of the search cursor function through the main ArcPy module. So you would need to use this if you have ArcGIS pre 10.1. I'm guessing that no one does, but if you did, that's what you'd have to use. But it still might be worth having a look at how that version of the search cursor works because you may come across some code that was built in those days. And it's going to be important for you to understand how that works. So here is an example that uses the one that we recommend, the one that's accessed through the data access module. And so this example here finds the state capitals in a city's data set. It starts out by setting up a reference to the USA file geodatabase that you guys even I think is part of lesson three. And there's a city's feature class in there, which contains a field called capital that holds a Y or an N if that city is a state capital. The name obviously stores the name and then state ABB stores the abbreviation of the state that the city is founded. And as I recall that, that abbreviation takes the form US-PA or US-NY, etc. So this example here, the first argument to the search cursor class is the feature class that you want to work with that has the tabular data that you want to work with. And I should point out that you're not limited to feature classes using search cursors. You could also use search cursors on plain tables, standalone tables that don't have a geometry in them. But in any case, the next argument you supply is going to be the fields that you're interested in dealing with. And when you supply the fields, you do so using some sort of iterable. And I don't know if I remember if I use that term in a previous lecture or how much it was used in the lessons. But an iterable is really just any sort of data type that you can iterate through. And so lists, probably the first thing you think of. But the other main type that you might work with here would be a tuple. And a tuple is really the same thing as a list, except you're not allowed to change the items in a tuple after you've defined it. And you probably recall that you define a list using square brackets around the items. A tuple, you have a similar set of items separated by commas, but you instead use parentheses rather than square brackets. So I've got three fields that I'm interested in working with in my search cursor here. And I close the parentheses on the arguments to the search cursor class, and I follow it up with an as clause where I basically define a variable that I want to store this search cursor in. And in a lot of examples, you're going to see that that variable is called just simply cursor, but you're not limited to that if you wanted to give it a more specific name. You could, you could call it city's cursor. You could call it the search cursor, whatever you want to. So you follow that up with a colon, and then the code that handles or works with the search cursor is going to be indented. And then typically what you'll see is a for loop. And you can really think of the cursor as being a lot like a list in that you can iterate through the items found in that object in that cursor. So you're going to do for something in and then that variable that you plug in after the word in needs to match what you call the variable on the with line with statement. And then this variable here after the word for again you have control over that typically you'll see it called row, but I could easily see it called the record or city row or something to that effect. And then within that loop, you would then make use of the object stored in the row variable. And you can get at the values in the fields that you said you wanted to work with by supplying a digit inside the square brackets. So you could you would say row, and then inside square brackets, you'd put zero if you wanted to work with the first field, or one if you want to work with the second field, etc. Okay, so you know what this code here does is it gets the value held in the capital field that why and field. And actually, I think I said it holds a wire and it looks like it holds a one or zero. So I'm sorry about that. So what it does is it checks to see is that value of one. If so, then we're dealing with a state capital. And, you know, this script is pretty simple it just spits out the names of the capital cities, as it encounters them. So if it is a capital city then then it says, Okay, let's get the name value as well, and state value, and let's print those print print the name, and then say is the capital of. And then this block of code here. This is where I'm going to ask people to chime in. Can anybody explain what's going on there with state file and then minus two colon inside the square brackets. Anybody remember what that syntax does. Doesn't it do the second to last all the way through to the end. Yeah, very good. Exactly. It says start to characters from the end of the string. And the lack of anything after the colon basically says, give me everything beyond that all the characters. And yeah so if the state of radiation column, as I said was us dash PA and you wanted the PA part only, then this is used to get that that slice of the string. So that actually takes us to the first little exercise that I wanted to walk through together. The data for this is the USA file geodata geodata base that we just saw in the previous slide, which is on page one 3.1 of lesson three. And we're going to work with the borders field in the states feature class. And the what we want to do in this exercise is write a script that prints the name of the smallest state that borders six or more other states. And so what I've got here is just an example from the previous slide that you can refer to as you as you as we go through this. So I'll open up Python when open a new Python script. And this is definitely something that involves using our pie so we'll start and then we need to have a reference to that states feature class. That's the feature class we want to work with here. So actually got to open our map here, because rather than type out this long path, and I have to update my license, rather than type out the full path to the data, but in the catalog window. Here's my USA file geodata geodata base. And I'll go inside there. Find states. And I might as well show you the attribute table. If you don't have it open already. And here's that borders column, which stores how many states are bordering each of the states. So, you know, with this the feature class highlighted there if I go up into the location toolbar up here and click, you'll see that it expands to the complete path to the data and selects that path. So I can see on my keyboard to copy that to my clip. And is there anything else I ought to do when I copy and paste in that way. Yes, but are at the beginning of it. Yeah, very good. So yeah, this is potentially problematic because of the use of forward slashes single forward slashes. Remember that I can use double forward slashes, or I can use backslashes single backslashes, or I can use single forward slashes but I need to put this lowercase r here. And I forget exactly what that's with you but I do know that the board slashes certain forward slash character combinations. It means something special it's a sequence to certain certain kinds of special characters. We want to do here, such as a line break paragraph things like that. That's not something we want to do here. So I put the Lord. Okay, so I'm going to want to set up a search cursor here. In my feature class that I defined above, and then I supply a couple of fields that it could be a list to, but because I'm not going to want to change this. I want the state name. I want the shape area. Remember the scenario here is we want the state that of the states that border six or more other states and the smallest one of those want to look at the area. And then the borders, and I close the parentheses to close that tuple, and then I close the parentheses around the search for arguments. And I'm just going to call this states cursor just to be drive home the point that we can call this whatever we want to we're not limited to. And I'll do for row in states. cursor, and let's get the name of the column zero. And what you know what I'm doing here is something that I try to drive home to any student that takes a class with me in programming. That is to take baby steps towards the ultimate. Don't try to bang out the whole. Go short steps at a time. And so I'm just going to see if I can get this to work. Save three. I'm going to create a demo folder here. All this. Not that. So I'll check the syntax. The syntax is good. So I'll hit the And the other thing that I drive home to folks is Use of F 10 to step through your code. Don't just hit the run button. Get an error and then Have an idea where the problem is use F 10 to Step through one line of time and Initially setting up the search cursor takes a few seconds. That's why we're waiting here. To get rid of these. Watch variable. Watch window variables. So that it does seem to be working. So I'll just go ahead and hit the run button to run through the rest of it. Okay, so that's a good, that's a good start. Now I want to look at the Borders column. I'll create a variable called borders val. Column two. To. And I want to do. If. Orders val. Greater than or equal to six. Let me do, let me do that same sort of thing. Not the name of the state. And yeah, that's a much smaller subset. So that's good. See on the right track. Now, I'm also going to want the area. That's in position one of the tuple. And at this point, you need to have some sort of logic to keep track of which one has the smallest area. So the way I would approach that is before the setup of the search cursor. Create a variable to hold the smallest area. And now coming back to the feature class to the attribute table. Here's the shape area column. And these areas are actually in square decimal degrees. Which is not something you really ought to use in a real life situation. Because decimal degrees are not a uniform measure of changes, depending on what latitude you're at. But. We're going to go ahead and use it. And what I've done here is I set up a variable. That's going to set up the variable, the smallest area variable to hold some large number that I know is bigger than the biggest area in that table. That way when I do encounter one of these states that has more than six. I know that that state will become the smallest area state. I'm almost also going to set up a variable to store the name of that state. Set that to an empty string. Initialize it to an empty string before we start. Generating through the states in the cursor. All right. So I've got the area value in the area of our variable. So what I can do is say if area val. Smallest area. Then what do you think I'm going to add a print statement. I could, I could. Ultimately, what we want to do is print. The name of one state, which we've determined to be the smallest state. And so at this point in the loop. I just want to, I don't want to do a print statement here within the loop. I want to wait until the loop is over. And I found the smallest state. So what else might I try to do here. To keep track of which one's the smallest. Any ideas. Well, what I'll do is say that. The smallest state. I'm going to. Reset that variable to be. Equal to name val. The smallest area, likewise. The area of the current state. We happen to be. Working on in this iteration through the loop. Okay. So. We're going to cycle through all the states. And each time we encounter one of these. One of the states that has six or more border states. Then we're going to jump. You know, We're going to go to the smallest area here. Then we'll get the area of that state and we'll check it and smallest area. And if it's smaller than all the other states that have been encountered so far. More border states. Then. We will reset what the smallest area is. And the name of the smallest state. And after the loop is all done. We should have found the correct state. And we're going to go to the smallest state. Ordering six plus other states. Is. All state variable. Period. The area is. That print statement. Does anybody see a problem with it? Anyone see a syntax problem. You'll need to put smallest area as an integer. Yeah, I want to. As a string. It's a, it's already. Number. Number with. The string function. Syntax syntax is good. I'm going to start stepping through here. And let me put. Name Val up here. Orders Val. All right. So the first state. In the cursor is Alabama. As a border. A number of bordering states of four. So this expression here. We'll evaluate to false. Which means none of this code inside is going to get. It means it's going to jump back to the top of the loop. Alaska. Which has zero. Again, we'll come back to the top. Arizona has five. Arkansas has six. So now at this point. That expression will evaluate to true. So I will do the stuff that's inside that if. I get the area. I check the area against. Smallest area variable. And again, that smallest area variable. I initialize to something really big. So. It's going to be greater than all of these. Happens to be actually. Roughly. So that's going to become the new. Small. And then I would continue through there's California. Colorado. Colorado's area. Less than. Arkansas's. No, I don't think it is. So. Back to the top of the loop. It doesn't do this. So you get the idea. And so I'm just going to go ahead and hit. I'm going to go through the rest. And. I did this same demo with students in a face-to-face class. Undergrads and they pointed out to me that they were getting. Rhode Island. Virginia. And. Rhode Island is certainly smaller. Let me see. My Rhode Island record only says two. Bordering states. Everybody hear me. Can hear you now. It cut out for a little while. Okay. I'm sorry about that. I'm sorry. I'm sorry. I'm sorry. The internet connection is spotty. Okay. So basically what I just did was I finished running through. The. Script. And got. An answer. So. That's one way that you could use a search cursor. To solve a problem like that. Anybody have a question. Any questions about. That example we just walked through. Okay. Can you. Re-share your screen. It looks like when you cut out it. Close down the screen sharing. Oh yeah. We'll do. There we go. Okay. And I just opened the chat box too. So if anybody's. Wanting to. Type something through the chat box. You can feel free to do that as well. Okay. So. Let me get back to. Slides here. All right. Okay. So. The basic use of the search curse. There's. There's some options to it. Take advantage of. Both the search cursor. Function that we recommend that you use through the data access module and the older ones. Aware clause parameter. And that refers to SQL structured query language, which I bet a lot of you have. Used in your work. Which statements are made up of clauses. And then. Fairly basic SQL statement, select statement. Here's an example, select name, state abbreviation from cities where capital equals one. So that first line. We would refer to as the select clause in that statement. One will be the from. And then the last one would be the where clause, which is what we're here with search cursors. And that that clause basically limits the records that get returned. To you from the overall data set from the overall. And so here's an example. Same scenario. Well, same cities feature class that we saw. To go. And instead of just getting all the records found in that feature class. We're applying a where clause saying that the capital. Field has to hold a value of one. Now the lesson I think shows that the field shows the field name being put in quotes. But you should know that that's not necessary if you're dealing with file based data formats such as shapefiles. And file geodatabases. So that's the case. You don't have nice because. This expression, the where clause expression as a whole has to be in quotes. But then if the field has to be quoted, then you're got you've got quotes inside quotes, which gets a little tricky. But when you're dealing with file based data formats, you don't have to do that. Some other search options. Actually, before we before we touch on these, let's make use of the where clause. In our example. So what could we do? How could we take advantage of that where clause option in this scenario? Anybody. It'd be used instead of the if statement for the border value. So saying where the border value is greater than or less than or greater than and equal to six. Yeah, exactly. So rather than having that. This logic here inside the loop. We could instead. Do that same sort of expression. As a where clause. So I'm going to copy that. And so you're going to add this. Argument to the list of arguments after the field lists or field. Are we defining. And. I'm actually going to be borders. I'm going to be referring to the field name itself. Greater than or equal to six. And if we do that. Then we no longer need. This logic. Because now we know that all the rows in the cursor. Are going to meet that criteria. So all we need to do is check the area. I'll just get rid of that again. And I get the same answer, which is a good sign. So that's a nice feature to be able to. Take advantage of when you're dealing with cursors. If you're dealing with a feature class. You do that by, in that field list or tuple. You would. Insert. What's referred to as a token. A geometry. So for example, if you just wanted the X coordinate value. Use the token shape at X. Perhaps. Same for the Y coordinate. If you want them both, you would do shape at X. Y. Or if you want the area, you could do shape at area. So here's an example where. Asking for. Name field. A column that stores the name. The column that stores the state. And then I'm also asking for the. X, Y coordinate. Now. You should note here that. It's going to give you. The coordinates. If it's a point, well, that's pretty. Simple. You know, it's got an X, Y coordinate. If it's a line or a polygon, however. It's going to give you the centroid. Of that. Line or polygon. And the other thing is the coordinates. Are going to be returned to you as a tuple. So. You would have to. You know, make use of them. Deal with that tuple appropriately. In your code. Okay. And then. My next point there is that you can also add in. Or make use of some other. Sequel features. But only on. If you're dealing with. Enterprise geodatabase feature classes. Or file geodatabase. Or file geodatabase. Or file geodatabase. Or file geodatabase. Or file geodatabase. Or file geodatabase. You can't use these features with shape file data. So the first one is you can have. What's referred to as a prefix clause. That includes the word distinct. So you would use that keyword in a sequel statement. If. The query. Or, you know, the data that you were getting back. Included duplicates. What those duplicates. So. or, you know, the data that you're getting back included duplicates, but those duplicates. So you would use the distinct keyword to basically eliminate all duplicates from the. You can also include what's referred to as a post fix clause. And the main reason you might want to use one of these, I think, is that you can order the data. So two examples here. The first one shows using that distinct keyword. So I've got setting up the search cursor just like in the previous examples with a feature class. Here I'm using a list of fields in which I just have one field in that list. Now the supplying these clauses, these prefix and post fix clauses, you actually have to skip over a few other parameters. And I should show you that, skip out of my presentation here, help system, look up search cursor, spell it right. And you can see here's the older version. This is the one I want, though, the arcpi.da. I go to the syntax section and see that there's the input table, field names, where clause, those are things that we've seen already. Notice the where clause is inside curly braces, which indicates that it's an optional thing. But then there's a spatial reference parameter and explode to points parameter. And then the sequel clause, read what the explode to points means. And here's, there's some discussion. So in order to get to set that sequel clause parameter, I need to skip over at least these two parameters. All right, so back to the slides. So in this case, I omitted a where clause. I omitted the spatial reference parameter and the explode. So notice in this case that that's equal clause parameter. If I wanted to just set a prefix clause, I need to put in what I want there, comma, and then just an empty postfix clause. And those two items are defined using a tuple. This example, on the other hand, I wanted to set the postfix clause. So I use an empty string for the prefix clause, comma, and then I put in my postfix clause. So in this case, I'm saying that I wanted my search cursor rows to be ordered by state abbreviation. Now by default, the ordering is going to be an ascending order. So from A to Z, or from one to, you know, starting at one to a hundred or whatever. If I wanted to go the other direction, I would add after the field name, I would put, whoops, I would put space D-E-S-C for ascending, ascending is the default though. So before we go on to spatial queries, I want to go back to the one we've been working on again, because we can make use of some of the features we just talked about, namely we can make use of the order by. And what I'm going to propose we do, well, does anybody have any idea how we could take advantage of the order by clause in this area? Maybe order by the shape area to begin with. So even though it's not going to get all the borders, we'll have to do something as well. You're still working in ascending size. Yeah. That's what I was getting at. Yeah. You can order by the area. And if you do that, then you know that, well, at the same time you've applied the orders criteria as a where clause, and you know that the first row in the cursor is going to be the one that has the smallest area. And so that's what I wanted to manage over here. So I'm going to come in here and I've saved a new copy of this script, skip over those two parameters that I'm not interested in. And remember that I have to supply, even though the thing that I want to add here is a post fixed clause, I also have to supply an empty prefix clause. Those two things together need to be supplied as a tuple. So I put empty parentheses here. There's my prefix clause. And now comes my post fixed clause, which is order by. Do that if I wanted to, but that is the okay. Now, before I go on, there was there was something that popped into my head that I thought was important to mention to you guys in case you haven't already the fact that I had to skip over these parameters. It's kind of annoying. Is anyone aware of another way to supply the parameters for or a this case, but you know what I'm getting out there. When you look at the syntax or a tool or a function like this, each of the parameters has a name. The first one here is in underscore table. The next one's field underscore names. So an alternative way of supplying these parameters would be to say in underscore table equals field underscore names. And if you supply your parameters that way, all of your parameters named, then you don't have to skip over parameters and you can put the parameters in whatever order you want. So that's another way to specify your parameters. And one reason I really like to point this out to folks is that thing that you should remember is that you can run any tool in our toolbox and go to the geoprocessing folder, respond there, go to the results window. And I haven't run any in my current session, but if I did have any tools that I had run, I could right click on the tool, I think, and say copy as Python snippet. And it'll take that running of the tool and turn it into a Python snippet, as it says. And I could then paste that into my Python win window so that I could make use of that snippet. And the reason I bring this up is Python snippets created in that way have the parameters supplied using the parameter names, the way we just talked about. So I didn't want you to be thrown off seeing the parameters supplied in that way. If you go to the Python snippet, getting back to the script, if I add this order by clause, I can change my logic inside here quite a bit. I no longer have to iterate through all of the rows in the cursor, really. I can just get the first row out of the cursor, and I can do that using a method called next. So that'll give me the first row in the cursor, and I don't need any of this. I don't need the looping code anymore. I'm still going to want to get the name, and I'll get the area value as well. And then my print statement, the track of the smallest one anymore, I would just get my name out there, and my area value. Let me run this. Actually, I don't need this anymore, right? And I also don't need orders in my field names. Let me test that out. So I still am getting the correct answer. Any questions about that? So there's a lot of handy options that search cursors have, and we just saw a few of them. So let me get back now to the slides, and we'll talk about spatial queries. So some database packages have spatial functions such that you can do spatial looking at spatial relationships between layers and things like that right within your SQL statements using where clauses, for example. But that's not something you can really do in ArcGIS. What you have to do instead, if you want to do a spatial type of thing, is use a tool called select layer by location syntax. You supply an input layer, an overlap type, and then a set of features that you want to use to select against, and both the input layer and the select features parameters need to be what are referred to as feature layer. They can't just be feature classes. There is a tool called feature layer, and it takes a set of input features, and that's where you're going to plug in a feature class. Then you're going to give, the second parameter is going to be the name that you want to give to this feature layer, and then lastly, there's a third parameter, which is an optional where clause with the features that you're going to stick into this feature layer. Here's an example. Shapefile called US Boundaries, I store the name of that shapefile in a variable. I have a, and inside that shapefile, attribute there is a field called state. It's got that US dash naming convention used. So I'm going to create a variable to hold the state that I'm interested in. And then here's the make feature layer tool statement. I plug in the feature class. I'm going to use a where clause that says basically I only want Pennsylvania. And then I'm giving a name to this feature layer of selected state. Here's a, taking that same little snippet and showing it in a larger context. So what this example does is it prints the names of all the cities within a specific building on what we just saw here, states FC, which was in the previous slide. I'm also creating a cities FC variable that holds a city shapefile. And I'm going to create a feature layer from the city's feature class. And I'm going to call that feature layer cities layer. And then likewise, I'll create one from the state's feature class, which is what we just saw. I called that feature layer selected state. And then I can do select layer by location. Because like I said, it wants the input layer parameter and the select features parameter to be feature layers. So I've created the two feature layers. Now I can do select layer by location. And I'm saying, give me all the cities that are contained by the selected state, contained by Pennsylvania, basically. Cities layer and selected state. Those are just objects in memory. Whose lifetime is the lifetime of those Python when those objects get. But as you can see here, I created those named objects. And then I make them refer to those objects by their names later on in my code. So it's a bit of an odd thing. A lot of folks tend to think of, sometimes people will put a .shp inside this name. And that doesn't really make sense because you're not creating a data set on disk. You're just creating an object in memory only. So you just give it a name that makes sense for your scenario. Okay, so picking up on that code, we were just looking at, let me go back again. So I created the feature layers. I ran select layer by location. After running that, this feature layer is going to have a selection applied to it. It's going to have a set of features. And I do that using a search cursor. So I run a search cursor over that feature layer. So the previous examples we saw, we plugged in a feature class here. But you can also plug in one of these feature layer objects. And that's what I'm doing here. And then it operates the same as if I was, what features or fields I'm interested in, and then I notice here that I supplied a couple of field names with just a single field name, but I followed that up with a comma. And you're going to need to do that in certain contexts. Sometimes you can get away with not, if you only have one field that you're interested in, sometimes you can get away with just having the field by itself. But there's other times you have to have a comma after it. And I don't, I can't pretend to know why that's the case. But it's always a good idea to have that comma there, that you'll never go wrong doing that. Again, if you're only dealing with one field, if you had two fields that you needed to use in your cursor, you could have those two fields. And you wouldn't have to have a comma after the second field. Okay, something to note here that's a good idea is to delete, using the delete tool, the feature layers after you're done with them. That basically frees up the locks that those feature layers might have on their underlying data sets. Okay, so that takes me to another exercise that I wanted to do with you, which is to use the Hydro and Cities feature classes in that same USA Geo database and write a script that prints the names of cities that are five miles or less from the Mississippi. Back to Python win script, so we start with that. And references to my two feature classes. And I'm gonna set my workspace, and let me come back here again and copy this half, Haitian toolbar and catalog. And by setting the workspace in that way, I'll be able to refer to my feature classes just by their names. I don't have to, so now I wanna create, ultimately I wanna do a select layer by the saw that requires feature layers. So I need to do that make feature layer step. I wanna do it, create a feature layer of the city's layer. Remember that this feature layer, this make feature layer tool has an optional where clause parameter. I want a subset of the cities, I wanna have all of them. Hydro, create a feature layer called Hydro layer. Now getting back to the scenario, let me bring in the Hydro table. And remember the scenario is we wanna find cities that are within five miles of the Mississippi River. I look at the Hydro attribute table, I have a column called nameN, which stands for name in English. You can see it's also in French and Spanish. So I wanna query that nameN column, right? And I wanna look for Mississippi River in there, all right? So I'll come back to my script and add a where clause here nameN equals, okay? So it's just like writing a attribute query through the GUI. When you are querying a string field, you have to put the value that you're looking for inside quotes, right? So Hydro layer should refer to just the Mississippi River, all the other rivers. So now I can do, select layer by location. You can see the parameters that it has there and underneath in that box. So what am I gonna put first? It's gonna be my input layer. If I wanna select cities that are within five miles of the Mississippi River. Would it be Hydro layer? Actually, no. We're gonna put cities layer first. Cities layer is the layer that we want to select features in. So that comes first. And then we want to have a overlap type. If I go to the select layer by location, down to the syntax section, you'll see that there's a whole list of the spatial relationships that I can see, the one that I would want in this case. You'd want within a distance, I think you said. Right. Now there's a couple other variants on that, within a distance 3D and within a distance geodesic. The geodesic would make sense if you take the Earth's curvature into account. We won't bother with that in this case. Five miles from the Mississippi River distances. So, plug that in, then we'll put in our Hydro layer. That's the thing that's gonna be used to select the features in the input layer. And we haven't plugged in the five mile part yet, right? So if I come back to the help parameters for the tool after select features, there's an optional parameter called search distance. You're going down the page, it tells me that this is a parameter that's valid when the overlap type parameter is set to one of the following. Within a distance, geodesic, all the within a distance options intersect. And if you pull down, I wonder if there's an example that shows using that. I don't think there is. So, this is actually a case where the documentation doesn't do a great job of explaining how you would do this sort of query. But what you would do is in that search distance parameter, you would actually plug in as a string or whatever the unit happens to be. So, as I said before, what that'll do is that'll create a selection on this feature. Plugging in a feature class here, as we did before, I will plug in your layer. And I'm gonna want the name, field names, tuple, cities, cursor, loop through it using a for loop, print the names of these cities. Zero, which will give me the name of the city where I add anything else. Get the state abbreviation, create a variable called state. And then I can use that since actually saw it earlier, I need to save this. Cities near this river, hi, okay, and I can run that. It takes a few seconds, but I do get the list of cities then that it. What's the reason you specified the state negative two? Because isn't the abbreviation typically gonna be two letters anyway? We look at the city's attribute table. See how it's got the US dash? Got it. And I just wanted the last two characters, so. And there's something in the chat box. I'm sorry, Danny, if you were answering questions earlier, I lost my chat box there. So looks like you had the right answers there. Now one thing that I could do, let's say I wanted someone else to be able to use this script maybe on a different river or I wanted to use it on a different river. Well, where that change would be required is here right now, right? And it takes a little bit of looking to find that. And so what I could do instead is store that, create a variable called river. I'm gonna move this stored in that variable and then variable for that was parameter. And then I've got a script that is a little easier to modify. Have it run on something. That's just a good practice. And I have one more topic that I wanted to cover. I appreciate you folks hanging on with me. I know it's gone pretty long and that is update cursors. So to perform a bulk update, you're gonna create an update cursor using arcpi.da.updateCursor instead of searchCursor. But once again, you can use a for loop or you should use a for loop to iterate through all the features in the cursor. differently from using a searchCursor, you're gonna set, instead of just reading values from fields, you're going to change the values that are held by the field. And then finally, you're gonna use a method called updateRow. So you do that, the changes actually. And just as we saw with searchCursors, you can apply a where clause to limit the features that you want. What's like with the searchCursors, you're gonna refer to the fields, by their position in the tuple. So let's see an example. Here is the boundaries feature class in that same geodatabase. And basically what I want to do in this example is, these are states. I want to set a region column in this attribute table to mid-Atlantic for the states of Pennsylvania, New York and New Jersey. So I set up an updateCursor. Again, the syntax is pretty similar to searchCursors. I supply a feature class, a fields tuple, what fields that I want to work with, and optionally a where clause. In this case, I am using a where clause, which I defined in this variable up here. And I used the in operator to supply a list of the states that I was interested in. I could have also done stateABB equals US-PA, or stateABB equals US-NY, etc. But this in syntax is a little slicker. So I plug in that where clause. Again, I'm going to give my cursor a name, the variable that holds my cursor a name. In this case, I'm just calling it cur, I think, because I was running out of space on my slide. And then I iterate through the items in the cursor, the rows. And instead of just doing, you know, like print, row, zero in square brackets, like we were doing before, or taking that value and storing it in variable, now I'm doing it kind of the other way around. I'm putting the row field number in square brackets for whatever field I want to update or change. I put that on the left-hand side of an assignment statement. And over on the right-hand side, I have the value that I want to set it to. And in this case, it's stored in this variable called region, which I set to mid-Atlantic. Again, just having that won't actually commit the change to the table. You have to follow it up with this update row statement. So you do cur or cursor, depending on what you called your variable. Dot update row. And then inside parentheses, you specify what row you want to update. And again, most examples, you'll see this variable here called row. But as I said earlier, you could call that record. You could call that, in this case, you might call that state row. I don't know. So that's how update cursors operate. And if you were to actually try to run this code, this note here says that you need to add that region field. And I just want to go through one last exercise before we call it quits here. And that is to write a script. So we've been dealing with that abbreviation field that starts with US-, right? So create a new abbreviation field and update that field, set its values to just that. OK. And I also have some slides on insert. I'm not going to go over that today. I'm here. This exercise on update cursors. Because it does have importance to the project. New script. I had my path work with the boundaries feature class. So I'll copy that. And before I do this, and I just ran through this with a face to face class, I'm going to kill this field because it has what I want to do. So there's state ABB. I'm going to re add that field that I just got rid of. And I have to remember how to do that. Table options. Yeah, that field. You are the text. And by default, everything is null. We're going to populate it now. So I'm going to have a variable called old field. State ABB, all new field, ABBR. And then I'll do my set up my update cursor feature class in my fields that I'm interested in. Or those variables. And I want to do this for all the all of the states in that boundaries feature class. So I don't have to use a where clause in this case, all this. And now I need to iterate through state cursor. And in this case, I'm going to call it state row just to make sure you you guys understand what change in the code and what needs to be locked into set and stuff. And so if I want to get the if I want to get the U.S. dash, that value, I want to lop off the U.S. dash part, but I want to get that value first. The ABB column. How am I going to get that value in my code here? What should my next line be? A variable called old ABBR, old abbreviation. Would it be old field and next zero? Old field is is the field in position zero in my tuple. Wait, so row index here. Almost. It's not row, state row, in this case. Sense. I decided to call this variable state row. Previous examples, it was always row, right? But that's completely under your control. You can call that whatever you want. In this case, I called it state row. So in my third of that row, using that. So that gives me the U.S. dash version of the abbreviation. We've seen lopping off the U.S. dash part new ABBR that I use to store. I want to take that value and stick it in that field. The APR field to do that. I would do state row. What am I going to put inside the new field? U, AB, R, that's the two character. But then again, I have to follow that up with parentheses. That that method is expecting me to supply the row object that I want to my slide example. I call that variable state row. And there's the last step here that is a good idea to do, which I don't think I've shown in my slides. And that is to delete and get rid of the cursor. All right. So I'll save this as update creation.py. There's nothing in my script that, you know, creates any output that I would see here and I'd have to come back here. And I think I need to remove this layer and add it back in to see the attribute table. And there we go. There's the ABBR field. So that's as far as I'm going to go today. You guys have listened to a lot, absorbed a lot. I also have some slides on insert cursors, but I'll be, to be honest, that's not something that's used in the projects. I'm not going to focus on it here. But at this point, I'll take any questions anybody has, any questions on the assignment, maybe, or anything else? Something small I noticed in the syntax of the search cursor earlier is that the SQL statement, even though in the syntax it needed to be at the end, it didn't look like you needed to put anything in between to skip over the other optional ones. Yeah. So getting back to the page and the help for the search cursor, the parameters ordered such that the input table comes first, then the field names that you want, and then comes the where clause. So we only plugged in empty strings, set this SQL clause, because in the examples that we were doing, we didn't care about this spatial reference parameter, so we used the empty strings to skip over those parameters. I see. I just missed the where clause last time. I think there was an example in the slide where I wasn't using three sets of empty strings, but I think I might have shown an example. It depends on which parameters you want to skip. Any other questions? Well, I hope you found this helpful and wish you the best of luck on your projects. It'll probably be a few hours before I can get the recording put up. I have to run back to the ice rink in just a few minutes, so I don't have time to wait for the recording to finish saving. But if there's nothing else, we'll call it quits here, and I'll be talking to you through email and the discussion forums. Thanks, Jim. Okay, thank you guys for taking your time out. I'll see you guys later.