QGIS expressions, variables, data defined settings: putting it all together!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Another excellent tutorial session from Nyall Dawson, streamed this morning from 5am his local (Australian) time to make it work best for the rest of the world.

Not showcasing anything particularly new - ie no newly developed features - just good solid basics of working with variables, expressions and data-defined symbology to increase the power and flexibility of your QGIS project.

Edit - it isn't showcased in the video, but you can see a new (3.14) feature at the bottom of the Expression Builder: A feature 'browser', so you can preview the output of the expression for various features. Love to see it

👍︎︎ 4 👤︎︎ u/Procrastine 📅︎︎ Jun 13 2020 🗫︎ replies
Captions
hi everyone welcome to today's live stream where I'll be talking about QGIS expressions variables data define symbology and tying this all together to make awesome flexible projects that work really well look beautiful but most importantly are easy to work with so they don't become like a big nightmare of maintenance can I just get a confirmation from somebody that you can hear me okay from the chat window can anyone give me a thumbs up to say yes great okay I've got confirmation I can keep going thank you all right so like I said hi I'm Noel Dawson from Australia where it's currently 5:00 a.m. probably gonna wake up my kids doing this again so if they sneak in the back that that'll be them thanks for joining me once again we did one of these sessions a couple of weeks ago on the new time handling capabilities coming with Q just 314 I really enjoyed it I I had a great fun time running that demo so I thought let's do it again and this time we're going to really dig into some of them the power of Q just I love I love teaching this whenever I do my in-person training it's something I like to spend a lot of time on because I think when you when you kind of this concept clicks in your brain and you understand how it all works together all of a sudden like the possibilities in your mapping just like your mind explodes so I'm I'm excited to do a session on this let me switch across to my QGIS window all right so the very first thing we're going to go through today let me put myself back here hey the first thing we'll go through today is I'll dig for a little bit about how expressions work in QGIS then we will look at variables and explore what they actually mean how to use them we'll look at data to find symbology and how you can use expressions to change the appearance of things in your map and then we're going to do a bunch of little little challenges and tasks that but take these free concepts and sort of tie them together to make different outcomes alright so the first thing we're going to cover is functions so for functions did at their most basic most people kind of experience them in cue just at the very first time through the field calculator which is this little button up here so let's have a look in here in the field calculator so field calculator is is the ability to sort of populate an existing field or a new field with a value that's been defined by an expression when we hit that button we get this this window up here with an expression builder and we'll keep coming back to this expression builder widget again and again for our today's session but to break it down we've got a few things here first off we've got the area on the left hand side here where I can actually type my expression so I can put in little expressions like 1 plus 2 one of the most important things in this window is down the bottom here the previews that we can see where we get a live kind of feedback of first off the current value of my expression that I'm typing here but also if I've made a mistake so if I've done something and put in an expression that doesn't quite make sense like here we've got two we haven't finished off the expression we get the nice little feedback immediately that something's broken we're going to fix that before we can keep going so that's on the left-hand side of this expression widget underneath it we've also got some buttons which just put in a little help common common bits of expressions that we tend to use a lot so things like a plus and minus equals exactly the same as if you typed it in on the keyboard as well but if you forget they're sitting down the bottom there so you're always kind of accessible next off in the middle here we've got the second most important bit of them the cutest expression build up so this part here lists a whole lot of different functions that are available for use in my expression and we get the help over here on the right hand side for them so let's have a look at one let's expand out the string section here and have a look at the upper expression the upper function sorry so you can see when I click on it in this in this list the the context help on the right hand side updates to show me the actual concert help for this particular function so upper for instance over here describes it as converts a string to upper case letters gives a bit of a breakdown about how to use that and then really usefully there's examples at the end so you can see here this expression if I put this into my into my builder over on the left hand side here here's the result that I expect to see where the arrow and you can see it's worked okay here so whenever you get stuck this is where you go you go to this help section in the middle you can look for your function you can search for them by name if you're not quite sure what what it was if I start searching for upper it's filtered out the list here and I can see again that help string on the right that describes exactly how that function should be used okay so that's our expression builder the widget here now there's a couple of things to to know up front about hugest expressions first off a lot of people ask what you know what language is this when I'm typing in a little expression here and I'm doing my upper and all that sort of stuff you know is a Peiffer as a JavaScript the answer is it's none of those it's a its own expression language which has been built specifically for kuja's but saying that it's been built in a way to mimic sequel expressions so if I take my upper function for example that one's basically lifted straight from the sequel standard so you'd get the same result if you used upper in Postgres or single server or something like that it'll work the same way so this expression language has been designed to be kind of sequel ish but it's kind of sequel plus a lot of extra stuff so it's almost like you've got sequel but then it's actually a bit more post crashes so it's kind of like when there's ambiguity we follow what Post Quest does but then it's a kind of post juicy so on top of that because there's a lot of spatial functions here as well if we look under like geometry you can see there's a whole lot of different functions here that relate to spatial objects and so things like a function that gets me the centroid so it's kind of like am the closest similar language would be post post juice the other thing to keep in mind is that the cutest expression language is what's called a functional language so everything is done using functions and the expression that I built here actually has to be like a single line sort of like a single single command built up off of chaining functions together so let's have a look at this let's do a really simple expression and do I'll get my uppercase function from over here I've if I find a function in this section here I can just double click to bring it over on to the left hand side so if I get my uppercase function I'll look under the fields in various section to find a field that exists in this table I'm looking at in this case name I've got a rapid in the brackets there to close off that function this is not terribly helpful this one because there's a whole lot of nulls in this name day let's try a different one i does not neither trying to find out well that's not death this data set wasn't particularly good one to pick but what i want to show you first off there there's a couple of traps in this expression builder that a lot of people fall into so the first one is if you want to type in a string directly like a literal piece of text that isn't part of the shouldn't be evaluated as part of your expression you need to wrap that in single quotes so if i do like a single quote and i type in this is my text you can see the preview out here is basically exactly what I typed in so the the single quote is a string value in my expression builder if I change this to double quotes this is actually the sequel way and so it works and qutuz expressions of saying this is a reference to a field in my table in this case my table doesn't have a field called this is my text and there you can see the little arrow here message is saying the column this is my text wasn't found it doesn't exist you so there's a difference if you use single quotes it means just take that bit of text as it is if you use double quotes it means get the value from the field with that same name so there's a little little trap that a lot of people fall into first off the second one that we have to be careful of is null values so you get a lot of things where in your spatial data you might have no values as part of a table null values have their own their own kind of special rules about how they work when you're putting them two functions so basically if I did something like five five plus a null value the results actually now it's not five like I'd get if I did five plus zero this null is like a special special empty value that basically kills everything else in my expression so we're going to be careful about that I'm not going to dig too deep into that if you're if you're interested in those concepts do a search on you could do a search on hugest expressions in the cutest documentation or just sequel sequel no in general and the same rules will apply to cutest expressions and have a little thing that I want to show you in cutest expressions is that there are things inside cutest expressions so values I use there they have different types so you can have number values you can have string values you can have date/time values and geometry values even but cutest tries to be a bit flexible in their in its expression so it's not like it's ultra strict about how they're treated a good way to exempt to demo this is if I type in a string if it's actually a number like 1 2 3 here so this is a string value I've put it in the little quotation marks there single quotes that means it's a string that contains the little numbers number digits 1 2 3 but I can do something like this multiply that by 2 Q just doesn't really care that this is a string it's it's been forgiving and it's decided well it's a string but it's actually a string that I can treat as a number so I'm going to do that I'm not gonna I'm not going to be pedantic about forcing you to convert this actually into a proper number before I'll let you do a mathematical multiplication on it I'll do that for you so there's different types of values in cutest expressions but it likes to be forgiving and it tries to take away some of that work about converting between them as much as possible alright so field calculator was one of the very first things that expressions were built for in huges but they quickly kind of spread throughout the whole of cutest so when when they were first added to field calculator it was sort of great everybody liked using them to update field values but it was quickly realized that they could be used in so many other places in QGIS so today if we go into my QGIS some some common uses for expressions would be things like having a label text that changes the let's pull off an expression its Select by expression rule-based renderers all these kind of stuff use the same cutest expression language so you can take expressions from one part of queue just use the same sort of thing in other parts of kuja's so let's have a look at that to start with if I have my I've got a layer here just a simple point lamb I'm gonna bring up the styling doc for this one I have a look at the the label tab so at the moment this layer has been styled we've using the name column from this this data set I could drop down this list up here and pick a different different field from that so if I change it to say locality you can see my my labels updated to show a different field value from from that table if we actually want to change this and we want our labels to show something that's not present as one of the existing fields in the table I can click the little button to the right of this widget which brings back up my standard expression dial expression widget like we saw before so I could change this and I could say actually I want my my labels here to be an uppercase version of the name followed by the space and the locality so I've just strung this expression here together to say get the uppercase value of the name column followed by a space this little character means I concatenate so add these strings together so we put a space there and then we put a space and in the locality and you can see here my my labels have updated so now I've got my my name and capitals followed by a space followed by the locality as it is so we can use expressions here to show the to change the label text dynamically another really common use of expressions is in the Select by expression dialog up here so let's click this one same widget up here but this one lets me type in a little expression to do a selection based on that so if I said find me all the ports where the locality is [Music] southeast Queensland oops so my expression is the locality equals southeast Queensland actually here's a really good example of the the difference between the double quotes and the single quotes so we have our field name is in the double quotes and now the value the the text string is in single quotes um I can do select features we've got three matching ones and you can see those those three there are features that match that expression got selected so that's another use of expressions really common use that select features using an expression option another part of cutis that expressions are used quite a lot on an almost daily basis is in something called a virtual field so you can have a virtual field which is basically like a tricky extra little field that's been added to my table looks like a normal field but it's actually calculated dynamically whenever we are we need that value rule-based renderers something else that expressions are used a lot in and they're basically scattered everywhere you can even do things like anytime you see one of these little controls that lets you type in a number in QGIS you can put in a cutest expression here and it will evaluate it straight away so if I did something like this 10 divided by 1.2 I could put in the little expression when I move away it's calculated immediately so any any kind of cutest expression would work here I could do it's complicated I want 10 divided by 9 Plus 8 times whatever on points to and I get my values straight away so same expressions same expression language syntax used all for our kuja's right let's have a look now at something called variables because this is where we start to get the real power of cutest expressions out said it to demonstrate this first off I'm going to make a print layout so I've just made it empty print layout here and I'll put in a new text label in my print layout and delete the default text from that um so in my print layout label we can put in expressions here from the insert and expression button so click here I'm gonna hit insert an expression and this time I have a scroll down here to the the variable section of the of the expression builder if I expand this out you can see a whole bunch of these things called variables have difficult access to and in this case I'm going to add one to my my label which is the project file name and I'm sorry the project path so you can see when I click project path here to help our text over here says that this variable contains the full path including the filename with the current project the current value is etc etc let's put that in there I'm just I didn't click sorry let's do it again project path double click to put it over into my expression all right so now my my print layout label contains the current path to the file the the project file but I haven't typed that in manually so it's like a little bit of dynamic text that will update if I went and save this project somewhere else let's save it to expressions view to bring back up my my print layout you can see that labels dynamically updated straight away taking the current value of that project path so here's a little tip for you whenever you're making a print layout in QGIS I tend to put in my templates something like this down the bottom where I've got my project path and then I'll do something like this put some brackets in there and insert the variable called layout name so that I can see when I print this out I've got first off a reference to the file name but I've also got a reference in here in the little kind of metadata section of my layout so we just layout that actually is this can be a huge help if you've got a massive project that might have you know 30 different layouts and you need to just reprint one of them if you don't have that bit of text in there you have to sort of dive through the project and actually find out which layout you're referring to but I can use that layout name variable here like I've done to dynamically insert that and again it's it's a dynamic piece of text this this variable so if I went and I renamed my layout master Depa so it's updated straightaway so in here again variables are a special little value you can put inside your expressions that contain a dynamic piece of text that's generated automatically for you you can recognize a variable because it's always prefixed by a little ampersand represent whatever um the little a circle symbol so all these variable names are prefixed by that same symbol alright now let's get to some some meaty topics one thing that is important and is actually fantastic about curious expressions uh is that they're context-dependent so I'm going to demo this yeah by let me just turn off some ways in my map I'm gonna change my my ports label here to something a bit strange I'm gonna change this to the variable that's called map scale so map scale the variable contains the current scale of the map to 69 as a current value which matches my scale down there let's put that here alright so now we're actually labeling these features with the current map scale and as you'd expect as I kind of change my map around i zoom in that the the labels are changing because my snap scale is changing but if I made a second map here by doing view new map view the scale of this map is different to the scale over here and you can see the same expression my at map scale is giving me different results depending on where it's being evaluated in kouddous so in the mat the main map over here where my scale is 1 to 600,000 we get one value in my second map where my scale is one-to-one million we get a different value for my labels if I went into a print layout again put a map in here at a different scale again say 50,000 I'd have to find like I'd say this scale 400,000 the same expression is giving me a different result depending on the actual context that it's evaluated in so how does that work let's have a look when I went into my labels to set it to map scale I have a look here under this variable section you can see I've got a lot of choices here of variables including a whole bunch of ones here did a map variables so we've got things here like the map scale map or like the center point of the map the width and the height of the map in in map units rotation a whole lot of stuff that relates to the actual view that that map is being rendered in if I instead went to something like my attribute table and I say let me do a expression base to filter on this attribute table and look in variables I don't have those math ones here anymore so I've got some variables I've got things like my project path in that that I looked at before but none of those ones like map scale are available anymore it comes up if I do a search because it was a recent one but there's no no value for it and it doesn't show when I look kind of variables it's missing so we're seeing different choices on what we can put into our expressions depending on where we're actually building those expressions so you might ask why don't we have the map scale as a choice when we're doing this an expression based filter in my attribute table the reason is because this attribute table it's not directly linked to any map view I could have multiple map views in my project let's put a few more in here and they might all have different scales when I bring up an attribute table if I was to try and say put the map scale variable into an expression in my attribute table there's no way of saying well actually I'm getting the scale from this map or this map yeah I map to or the main map or even the the map from my layout because possibly my layout might be the one that is is visible behind here and you know it's not directly linked so we don't see the map variables showing in that context similarly if we went into a field calculator in my layer properties we also don't see the map variable showing here because again they're the field calculator that's not directly linked to a map view you can have multiple map views in a project and you don't know which field which map you want to calculate using this scale for that so the way this works is that cutest expressions context-dependent we get different values depending on where they're being evaluated and that context is also controlling what we can use inside that expression I've got some I've got some Lego bricks here the demo this so basically we have this concept of these things called expression context scopes and they build off each other like Lego bricks so you have things like in one context you'll have a whole bunch of variables related to your project when I'm evaluating an expression in my my map window I get a second set of variables out of on top of that which relate to those map settings we can we can explore this a little bit further from the ground up if I go into my settings option in a QGIS window settings options there's a tab here called variables you can see here when I go to my variables tab we've got a bunch that have been pre-populated for us these are in italics because these ones are actually ones that cue just generates internally so I can't change these if I double double click on these or change the values of them but you can see we've got a bunch of useful ones here so things like there's one that's been automatically created with the user account name and my user full name so that's sort of taken from the operating system user profile we've got ones for the cue just version you should ask you just version numbers also like the operating system name and the current locality so all these ones that are listed in this settings option expression variables tab are things that apply across the whole Kudus install so it doesn't matter which project I've got loaded in it's still the same cutest version doesn't matter which map window I'm looking at we're still using the same operating system or it still has the same logged in user account so these variables here are ones that called global variables they apply across the whole of that QGIS install on that computer we can actually set it up yeah these are the global variables in this little editor there's a plus button down the bottom where I can hit this one and make my own global variables so when I might make here might be the organization name let's put in one North Road so I can make my own set of variables which has stored globally in QGIS it doesn't matter which project I load on that computer that same organization name variable be available to peruse we could see these ones here the ones I've added manually don't show in italics and I can get in there I can double click and change those values so actually I better fix this and do Pty Ltd on the end I could change these ones the ones I've made myself I can't change the built in ones so now we've made one here a global variable for organization name let me bring up my print layout again yeah it was the one so let's say I put a label into my my print layout get rid of that default text and I'll insert in here under the variables section we have a look that new organization name variable we made is available here for you so you can see again that the current value over here so I'll put that into my expression builder and it's put that little bit of text in there now so my my layout label is set to follow that organization name variable let's put the value in there if I go back in here and let's change this get rid of that extra bit it's still a dynamic value so it's it updates when i refresh that layout because it's just taking the value of that organization name variable I've got a question here in the chat window about changing a date/time field or getting a string into daytime I might cover that a bit later for a good time because it's a little bit off topic for this um right so my organization name variable is a is one of these global variables that I've set up manually and they'll apply regardless of the project that I've got loaded into kuja's so that's kind of like the bottom the bottom building block of our cute expression context is the global variables the next one that sits on top of that is something called project variables so let's put that one there we can see these ones for our project properties window so project properties also has a variables tab here and you can see when I go in here this is where a whole lot of project related automatic variables are coming from so things like the the project path that we saw before is coming from that project project scope i've got ones like project file name the project CRS or all these have kind of wonderful stuff but we can also see at the top here there's a little collapsed section for my global variables and the reason this is is because like we've seen with our Lego bricks these contexts a stack on top of each other so in my in my project whenever I'm evaluating a layer expression inside a project I've got the option of using variables from the project all those global ones that are available regardless of the project now one really cool thing about curious expression variables is that they they they kind of act a bit like CSS if you used to web development where you can override things from at a lower level so if I went down here and I add a new project variable and I call this one organization name and let's say my organization name for this particular project is actually hugest org I'm doing it under a different name because whatever so what we see here now is I've made a new variable in the project scope but the same name is something tailored that matched my global scope and it's put a little cross here to actually show me well this is that the global value through that variable but it's not applying in this anymore because I've overridden it down here for this particular project if I look in here in my layout now the project value for that variable has overridden the global one and now we're actually seeing a different a different result for my label so this is kind of neat I've got my default Organization name that I've set up for my whole install and all my print templates use that organization name to say produced by but for one particular project where I'm doing it under a different name I can override it and decide for this one I want a different value for my organization name I don't have to make a new template for it because my templates just using that variable that's been overridden for one particular project so we've got now now our global variables that can be overridden by the protec variables in the when we saw in here that we also had variables like the map ones this is another set of context another context that's been added to make it available for those variables so this is the the map context basically where we've got all those things available the map scale the map rotation and such are available because our labels are directly associated with a particular map view so when I'm when cutis is rendering these labels it knows which map it's being rendered in if I had multiple ones it knows exactly which which map this is referring to because the label is sitting inside a map so we have like a map this map scope as well it's sort of sitting on top of our global and our project ones there's a map level one two we've also gone third to finalize this picture this ad does layout level scopes and layout item scopes so if I have a look in my layout and the general properties here and I scroll right down you can see I've also got a variable editor here that applies to this whole layout and the variables for my layout - first off we've got the global ones then we've got the project ones and then we've also got layout ones so again I could decide for one particular layout in my project might override this value for organization name and change this to great maps Inc so now we're not taking the value from our global organization name anymore we're not taking it from the project one we're actually overriding it specifically for one particular layout inside a bigger project and now this is the value that's being used inside my layout item organization name so there we go so we've got this concept of variables that built up off the top of each other and they can override values from a lower priority part of a lower priority part of that expression context all right let's dive back into my my map view let's change this one back to something a bit more sensible and we're going to look at something called data defined controls for symbols because this is the last the last part of our puzzle about how to make these wonderful adaptive cutis projects so data defined controls let me load a new layer into my project actually just put this one in so this is just some towns town locations from the natural earth data I'll make this a little bit bigger and a little bit less ugly all right so now I've got some towns showing on my map you when we talk about data defined actually got a question over here in the chat window asking if a variables value can be an expression it actually can be and there's a there's a function called at sorry called eval evl so this one if you wrap that around a variable that is itself an expression it'll all work as you want so yes you can do that um right if I look in my symbology tab for any layer and I go into my simple settings you'll notice that there's a whole of these little buttons that sit to the right of controls here and when I hover over it it gives the tooltip says it's a data defined override these are next to almost every single setting inside qjo symbology and labeling and print layouts and all this kind of stuff so you can see I've got them sitting next to my size next to my fill color stroke color all the way down to things like the offset if I change the symbol type to a font marker I've got them next to the the font family all this kind of stuff the character to show um and what these little settings actually let me do is they let me control on a feature by feature basis if the value for that that property should be changed based on their actual feature that's being rendered so the easiest way to demo this is let's say I want in my map here I've got my labels switched on let's make these a little bit smaller again let's say I want to make the most important cities the biggest ones their labels should be bold and they should be bigger so there's two ways you could do this so one way would be to set up multiple different layers and you filter them out to say this one is only my important ones this one's not and we'll style them differently you can do that but then the problem is your project starts to become more difficult to maintain because now you've got two copies of that layer that you have to sort of keep in sync and if you want to change the one is the colouring of one you've got to apply it to another um you could do a similar kind of thing using a rule-based label system but again you're still managing multiple sets of label settings whereas all we want to do is we want to keep everything else the same same font same color but we want our big cities like the capital to be shown in bold and the rest just in the normal text this is a great use for these data to find overrides um so in this case what I want to do is I'm going to click on the the little data define button next to the bold setting and I'm going to hit the edit button to bring up my expression builder and I need to type in a little expression here which will be which will evaluate to a true value for my important cities and a false value for my not important cities and the way I'll do this for this particular data set is I'm gonna look at the there's a scale ranked field and I want to say if my scale rank is western or equal to free then it's an important city so basically it's smaller the scale rank in this data set that they're more important in that city is um and there we go so now as its as cutis is drawing each of the labels for those features its evaluating that expression to check if the scale rank is less than or equal to free and anytime it is the label gets a bold gets rendered in bold so you can see this one here where's my scale rank for this feature do again its values three this one here it's various seven so it doesn't get rendered in the bold and I think there's another one up here somewhere maybe not in this data set yeah so now my capital has been rendered in that bold text because it passed that little expression that I put in there where I said draw it in bold only if for this particular feature that scale rank value matches that criteria I could do the same sort of thing for my font size so I could say let's build an expression here and for my my font size I'm gonna say I'll use a sequel ish case statement so again if you if you haven't seen this before do a Google search for sequel case statement and you'll find the explanation but I'm gonna say case when scale ranked less than or equal to free then my font size can be 18 otherwise it can be 13 and when I do that you can see my my brisbane label there just jumped up because now it's the only one being rendered in that font size of 18 the rest are getting the font size of 13 so basically every time as it's labeling every one of these features its evaluating these little data to find overrides to decide if on a feature by feature basis we need to change the value that we've preset in here so they called overrides because they're basically ignoring this this value I've typed here and replacing it or something else but dynamically feature by feature so this one here it was quite you know for my size data defined override we needed to write a little expression here that returned a number so it's basically the font size and points is that is the value we're returning him for something like a color setting like here we've got a data defined color let's do let's try and make the capital city red in this case so we'll go case when let's say when the name equals Brisbane then vote for a color setting like this one we actually return the color in a HTML color syntax so I could do like hash Oh otherwise black so we can see here so as it's deciding the color for each feature to render it's checking that name if the name is Brisbane then this is the value that'll get the color value if Oh which is a red color otherwise black and there we go so now I've got a red label for my Brisbane one we can tell that when I did my edit this is handy little bit of text down here that lets us know the expected value that we need to get back from this expression when I did it for my size you can see here the expected format so the value that expects to get back out of this expression has to be a double so like a numeric value with a decimal point possibly and has to be greater than or equal to zero that kind of makes sense like we don't want a font size to be less than zero doesn't make sense for my color one the little helper was saying it wants a a string value and it wants it to be like a hash rrgg be be hexadecimal sort of HTML style color value all right so that's that's the basics of how you set up data to find settings for a symbol we can do the same sort of thing from the labels and we could do it in the symbols as well so the form is an actual symbol style so I could say in here my symbol style I also want this one to change let's see if I can use the same expression even so when the name is Brisbane we want a red color otherwise we want black and there we go so we can use the same expression as a data defined override for my marker fuel color as well um now there's two special little tricks that we can use with variables and data to find overrides when we're styling our map here one of them is there's a really common task that people want to do where that's I'm just going to reset these ones back again to reset this clear that if we were actually styling these this layer as a categorized renderer let's do it by scouring for now um so we've now got a thematic map showing these places by one of the attributes in the in the data then it's changing the color for them a common task that that people will ask about is how we'd actually get the labels to match the same color as the the markers themselves so one way would be again to set up data defined override for each of those different criterias so you could say in my expression I could write one that says case when the sky rank equals one then this is the color value when the sky rank equals such that gets pretty complex quickly because first off your expression is got to be massive and then secondly if you change any of those colors you'd have to go back and update that expression but there's a really nice thing when I go to put a data defined override on this symbol the label color we can see there's a variable over here that it's sort of hinting to us called symbol color and this one the this variable contains the color of the symbol used to render the feature so let's put this in as my label color override and you can see now what it's done is for each of these features it's actually taken the color from the categorized renderer and use the same color for the label the great thing about this is if I go in here and I say that's that's pretty horrible let's fix up some of these colors and make this something more readable my my labels are updating in exactly the same time it's taking that same color as my my little marker symbols so I don't have to try and manage two sets of rules don't have to manage two sets of colors as I change them it's just using that that wonderful symbol color variable to say get me the same color as my symbol itself is rendered in so now I could go on I could fix up my coloring to make that something more usable and I only have to change it once we get that nice immediate feedback as well when we're changing they're the categorized colors um let's reset this back again there's one other really special variable that's available in symbology which is there's a variable here that's just called value now this is a funny one because this one first off it doesn't have much help but secondly what this actually does is the value variable gives me the value of whatever has been put into this widget here so usually when I put a value in for my expression it's an override so if I put in a value here let's say it's 19 it's ignoring whatever's put into this size field now doesn't matter what I change this to because the data defined override is is wiping that out and saying no don't use that don't use whatever I've put in here you actually need to use the result of my expression instead but this this kind of magical value variable this actually just returns the same value as I've put into this widget here so this lets me do something like like I could say case when my what was that field called when my scale rank is less than or equal to free then get value and double it otherwise just use the value so my expression looks a bit funny now because we use we've used about you here twice but let's have a look what this does so now when this expression is being evaluated it's taking the value from this widget replacing that at value part of my expression with whatever I've put in here and giving me the result so now I've got the flexibility to actually change these values using the interactive widget and you can see my my data defined override has sort of adapted to that and now we've still got our Brisbane label the capital city label is twice the size of everything else but I've got the ability to get in here and still customize the the font size dynamically so I haven't baked this value in I've used this magical little add value at at value variable to just say replace it with whatever I put here this works for all this sort of stuff so you could say and add value when it's used for a color override would actually be the value of the color I put here when I use it for a say a fonts name one it would actually be the value at the font name that it's been picked down here so it's a special little one that you can use to mean that you've still got that ability to into actively control things but adapt them feature by feature so still without double size Brisbane label that we can change things dynamically still alright I've got a few minutes left and this is where I'm going to tie all these concepts together to teach a few tricks that let you make projects which use expressions variables and data defined controls to tie them all together alright so the first thing we're going to do here is I'm going to teach a little trick that I like to use a lot when I'm making maps whenever I am making a map project I tend to go in into my project properties the variables tab and I'll make a new variable in here which I'll call label font and I'll give this a name what's a font on my computer let's just put a Arial for now cuz I know it's there so I've set up a project variable called label font and I've given it the name of a font here um when I go into my data defined override for any of these labels these layers that are labeled in my map I can pick to set this this expression to match one of those layers those variables that I've set so I'll set it to my label font variable so now my font that the labels are being allowed but are being rendered in is taken directly from this label font variable which is currently set to Arial and I could go and I could say all of my different for all the different layers in here I'll set them to follow that label font variable for the font name suevel well see so I might have you know 50 different layers or something in a complex project and I've set them all all the ones that are labeled to take the the font name from the label font variable the reason I'll do this is because I tend to do things where I'll I'll get sort of 80% of the way for a mapping project and then decide I think actually the problem with this map is that the font choice was wrong that font choice I made right back at the start when I was putting all those labels on my map wasn't a great choice and actually should have used a different font that means that I would have to go back through and I would have to edit all 50 layers and change the font for each of them I'd have to go back through one by one so change my font to something else and hope that it gives a better result because by the time I've done that I don't want to have to risen return and revert all those changes if I've used a variable for the font name it means I've got one place that I have to change that so I could go back in here and I could change this to say Comic Sans as my label font when i refresh my map now all of the labels in my map that are using their label font variable as an override for the font name have been updated in one go so I've got one place now that I can change that will but I can use one place to say those two Calibri and test different fonts to see which one I actually want to use for my final map instead of having to go back through 50 different layers change them all and hope that we're getting at a better result so it basically means we've we've saved a whole lot of work we've now got one place to change a setting that applies across the board for my map I'd actually do a few things in here I'd probably go in and I'd have a variable on a project level for for label font for my most important things that might be like label font important and maybe this one's a different font maybe this one is correct sans for my most important labels and then I choose on like a layer by layer basis which variable I want to take that from there's like a little little mini hierarchy still means I can change one place to update a whole bunch of layers and I probably would do things in here as well and set up ones for like the default label size so maybe with my default label size for this project is nine when I'm labeling my layers I'm gonna say take all these ones get my default font size from label default label size go back and do it for all these ones I do when I'm first setting it up and now I've got one place I can go and say mm let's fix this that wasn't quite right my labels need to be bigger across the board one place I can change it applies across my project so I can now do these kind of whole project level tweaks even though I've got a massive project that's got 50 layers in it and it's sort of half that 90 percent stage where it's the the little bits changing a font size by half a point might make all the difference in an awesome map or a terrible map all right here's another tip here's another tip I really like this one let's get rid of some of these labels we don't want this one let's turn this one off turn this one off too okay so if I had this all right so I've got my labels set up to this layer here for my populated places label in this case what I would generally do in a project like this I don't like how these labels are being placed what I want to do for this project zoom out to be I'm gonna just fake some settings here until until I get the result that I want to see sorry just give me a second to tweak this stuff all right here yeah that's good okay so I've got my my project has been set up I've got some labels here for populated places here's the scale that I'm working on that I want to print it out at I would get to this stage and I'd get a bit frustrated with my project because I want to follow those sort of time-honored cartographic principles where a label for a feature that is sitting on a like a coastal boundary actually should be labeled inside the the water part if you look in any old sort of cartography textbook that'll be one of those rules they'll teach you I remember learning it when I was studying cartography at University and I really liked it so I want my map here to respect that so what I want to do here is I want to set up a data defined override so that the labels which is sitting along my coastal areas actually have to sit out into the water area this one here for instance I'd want that to sit up here this one here especially that should be sitting up in the water area the the automatic labeling by default in this case has decided the bottom left a better place because I said I put a rule in here to say minimize minimize putting labels over there the boundary of my my state boundary layer so what I'm gonna do to to fix this is I'm going to first off go into my fields for this layer and I'm going to make a new field and I'm gonna call this one my fields called is coastal and we use a numeric ended your type is fine for this okay so we've now got a new field in that in that layer called is coastal I've got a question here actually in the chat window about what base map background I'm using here it's not a standard one it's just a vectors rendered using some nice CUDA settings sorry I can't I I might cover that in a future topic but um anyway so now I've got a is coastal fjord in this this layer and I'm going to set this up so I'm gonna say in my label for my places under the placement tab when I've set this to the the cartographic mode there's this option here that I can set as a data define setting for the position priority for my labels so I'm gonna go in here when I look in my edit there I've got a visitor again you're gonna say hi to everyone alright so my my little help text here for the expected values for my my position priority data defined control gives us some strings here so it says my expression should return a comma-separated list of placements in the order of priority so my expression for this case for this one is going to look like this so case when my value is 1 then the placement the placement overrides my Mike's getting all tangled up um my placement overrides string here is going to look like this so I prefer for my coastal labels first stuff on them I want them in the top right by default so TR you can see down here is the this string which represents top right if you can't do it the top right put it in the bottom right if you can't do that just put it on the right of the future okay so when when it's a coastal label this is the priority string we should use we should use the top right followed by the bottom right followed by the right so that's my position priority data defined override the last thing I need to do is none of my teachers actually have a is coastal value yet so I'm gonna have to go in here and I have to say let me select let me select one of these features and I'm just gonna update this so use coastal is one for this particular feature you can see when I did that the label moves straight away so undo that when I when I didn't have his coastal set to one for that it's using the automatic placement we just decided bottom-left when I changed it to add his coastal now it's being restricted to my data defined override which said for my coastal ones it can be top right it could be bottom right it could be on the right or nothing they're the only choices it's allowed for my coastal ones so now I can go I can make a selection of all my coastal towns let's get these ones Makai these ones Bundaberg hobby Bay here I'll use this this button that does multi attribute update set all these ones that is coastal to one and there we go so now my coastal labels my coastal towns have all been restricted to say put your labels on the top right at the bottom right or the right and don't don't allow them to sit on the left hand side so now we've got that um that nice cartographic principle where my coastal towns are actually labeled inside the coastal regions so there's a little trick so that we in this case what we're using is a data defined override for the position priority and we used a value a new field that we made for this particular project alright now for the last thing I want to cover today is is one of my all-time favorite tricks in the inside cue just for making great adaptable projects I'm just going to reset some of my settings here again because I want to get back into here I'm gonna get back to the stage where if I still got this expression yeah okay so we're back to our our map where we've set up that data defined override our capital city is in a bold font and bigger I'm really happy with this map how it looks here but let's say in one of my print layouts that's attached to this project I've got this map sitting here and I actually don't want that like it's not it's not a good it's not a good fit through one particular layout inside my project so in general I like it for my 99 other layouts inside that project having the capital in bold is a good choice but this one layout here I don't like it being involved this is a sort of thing where you can get really tricky if you don't know that the right way to approach it because you could you could set up different themes and maybe you linked that map to different styles but we can actually do it all through data to find overrides now the thing that I want to teach today with this is there's two ways we could do this so one is like a bottom-up way and the other one is a top-down I wanna show you the the inferior way first and then I'll show you the better way so probably the standard way that someone would go about fixing this to say this one layout here I don't want my labels to be bold but in the rest of my layouts and the rest of my maps and this project I do is you would go and you would say I just have to do so so I would I'd click on this map I would find the ID section and first off I'd give this map a fixed idea so I'm gonna call this my state layout map okay so now this this maps got a fixed ID and called state layout map let's copy them so one approach to this will be to go back into my my main canvas go into this data to find rule and say let's do it for this one for the size and say first off case when we've got a variable here called map ID and you can see the map ID variable is the ID of the current map destination so it will either be canvas if it's being rendered here or the item ID if it's inside a layout map so I could say when the map ID is state layout map then all my labels should be size 14 we don't want that capital to be bigger otherwise it goes to that secondary rule which is based on the scale rank so let's have a look at this again so we're saying if the map ID is my state layout map all the labels and that layer should be 13 regardless of the scale rank but otherwise use this this special rule here that says their scale rank dependent so let's have a look in my canvas still the same result we've still got the label size like that when i refresh this map now we've switched off that that dynamic sizing just for this one map so we've got one map here where we've switched off that so that that's one way we could approach this problem of saying we don't want that dynamic sizing that dynamic bolding in one particular map the problem with this approach is it's really becomes a maintenance nightmare we've got how rule here is starting to include things logic it's starting to include parts of the rest of our project so it's got this hard-coded thing in here to say when the map IDs state layout map if I went and I change that map layout ID I'd have to remember to go back and change all these data to find overrides that might be referring to it but this is super tricky can take a lot of time if you miss one then you might break the layouts just subtly in a way that you don't realize until you actually see that map in production and then you're like um so this is the inferior way to approach this problem here's a better way to do it if I was coming at this one and I had to say some of my maps will have a big capital name some of them won't first off I'd go into my project properties put a default variable here so this one will be called let's call it use big labels for capitals so I've made a new variable that's called use big labels for capitals the default value for this project for that one should be 1 so 1 means it'll it'll be true it'll like a yes value okay so now I've got a project level variable for that and I change this I um and instead of hard-coding in that map ID rule I'm going to just change this to say let's tweak this a little bit when my variable of use big labels for capitals is true then we use our scale dependent sizing otherwise we just use 13 okay so we've removed that hard-coded layout name that we had in that and we're just saying use a variable now so case when the variable value for you use big lands for capitals is true then we use big labels for capitals otherwise we just use a hard-coded value of 13 so now in my my canvas we're still seeing the result we want it's using that default value from the project if I bring up a Lam this one in my layout my default layouts inheriting that value from the project's the project context so that's showing them in capitals but if I go in here into this one particular map that I don't want them to show in in its variable section and properties down the bottom I'm going to add a new variable which is use big labels for capitals and this one is no so now the the project setting for that the default one that was saying yes is being crossed out it's being overridden just for this one layout item to say no let's refresh that and there we go so what we've done is we've changed the logic from sitting entirely in my labels data defined thing with a whole lot of hard-coded values about this particular map it shouldn't be like this this particular map it should be like this we're now using variables and just overriding that variable for one particular map to say actually just for this map let's switch it off I could put another map in here it should use a default setting I could put a third map in here and I could say actually for this map as well I don't want it so this is now a nice easy fix I can just say put a new variable on here I write it for this one and we've actually now changed it so that logic that was sitting hard-coded in a lair somewhere in our project is now directly visible or directly settable inside the layout item itself so the toggle that lets me switch on or off that setting has been moved from sitting at the bottom of our project to sitting just at the item where it actually applies to umm I like to use this sort of thing for cases when I want to hide just particular features from a certain map so I might say in in this map here I don't want to see anything except for a few like the most important ones I'd use a similar set up and basically put a rule based render out in on my places one with word has an expression to say depends on some it checks to see if Inuk excluded labels variable is set and if it is then don't render though if the label text is part of that excluded labels variable so that's sort of like one way you can also use this same sort of thing of like a setting options in the variables for a layout map which apply all the way back down when it's rendering just for that map there I've got a bit over time but maybe I'll have to do part to you next time this has just been a kind of whirlwind introduction to expressions and expression contexts and variables and kuja's the most important takeaways if you want to really watch this video or if you want to make notes for yourself you need to think about how those expressions context-dependent so the same expression evaluated in multiple different parts of your project can end up with completely different results depending on the wider context in which that expression is evaluated you also want to think about how those those contexts are like building blocks and they build up from your your global variables with your project variables and then you can have layout variables that override and it's a bit like CSS and the ones from variable values from higher in that stack override any that are set below that and most importantly if you set things up to use variables on a project level or on a inside your project you can you can make these projects where you change one variable and it can apply to hundreds of different places in that project so instead of having multiple parts multiple settings scattered for a project that you have to update you can pull that all back into one central place where you can make one change and update that whole project as a result um a couple of questions on the chat window I've got one here about any places to read up on this topic one place that I would recommend if you go to Google there's a blog post I wrote quite a few years ago so if we search for Niall Dawson expression variables you'll get a blog post from 2015 on my old blog this all still applies and this is a great written sort of summary of a lot of what we've talked about today looks tiny bit different because this was you just 212 but the actual uh all this stuff still applies at the windows will just look a little bit different um that's a good place to read up on it another one that I would highly recommend which uses a lot of this concepts is the book hugest map design second edition where we we go cutest map design second edition from locate press this one covers a lot of this kind of data to find things and variables and expressions and it's fantastic so that this is like a [Music] it showcases different maps and then in that were maiden cutest and then it explains over the next couple of pages how they were actually put together fantastic for learning more about this sort of stuff so QGIS map designed by Anita grazer and Gretchen Peterson second edition locate press great place to read up more on this one I think that was all the questions that I had outstanding yeah great thanks for joining and let me know if you've got ideas for future ones like this that you really want me to explore in depth make a comment on the YouTube video and we'll see what we can do next time thank you very much
Info
Channel: Nyall Dawson
Views: 13,023
Rating: 4.9668508 out of 5
Keywords:
Id: h-mpUkwDdOQ
Channel Id: undefined
Length: 81min 20sec (4880 seconds)
Published: Fri Jun 12 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.