 Well, hello and welcome. Happy Tuesday. Thank you for showing up today for my talk, SQL Like Joins in Base R. And I'm Monica Wahee and I teach data science and I do data science. And if you wonder what data science is, it's, I guess, science, right? I'm an epidemiologist and a biostatistician, but I do data science. So you've got a data question, I'm the person to ask. And so today, I'm going to answer your data questions about SQL Like Joins in Base R. Doesn't that sound nice that they're SQL Like? So why am I excited about SQL Like Joins in Base R? Well, if you're a healthcare analyst, like you do health analysis, like you went to school for biostatistics or epidemiology like me, well, you don't really learn SQL or maybe you do now, but most of the time, the thing they teach you is SAS, which is a really good program to learn. I teach SAS, if you're having trouble with SAS, it's a hard program, but it's good to know it. But SAS does not do joins. I mean, you can make it join the way SQL does, but the terminology is not joined. The terminology is merged in SAS and how you approach the programming is different. I mean, the results is the same. You take two tables and you hook them up together and somehow, when you're done, you get one table. That's a mush together version of those two tables. And the deal is if you're doing it in SAS, you're using the sort of sort, sort merge that probably sounds familiar to you. But if you're doing it in SQL, you're like sort, sort merge. What are you talking about? It's join. I do left join and right join. Okay. So already we're all confused because there's these different sets of terminology, but regardless of whether you're using SQL or SAS or R or anything, you can execute these joins or do these merges and get the same data set as a result. It's just terminology. That's all it is. And the terminology follows the actual programming. And so that's why the terminology is different. Okay. So now let's go into R. Let's make it even more complicated. Okay. So R is open source. Okay. And SAS is not. So I love R, right? And when people built R, they thought about what people already knew out there and a lot of people already knew SAS and SAS like languages. So if you download and install R, you'll notice that it's pretty lean program. Like there's not much in it because it depends on you installing packages. Okay. So in base R, if you want to do joins or merges, remember the same thing, just different programs, you want to do that in base R, you're sort of doing it the SAS way. Okay. Because you have merge and stuff. Live people don't like that. So what they do is they say, I'm used to SQL. I don't want to use this base R. So I'll use this package. Deplier. Okay. Like I have on the slide. I didn't even know why they called it deplier. It's like pliers, right? Like you can use tools and pliers. It took me a long time to figure that one out. But the package deplier is a great package. If you're used to programming in SQL, you're just doing the same data management things you would do in base R or in SAS using, you know, it's just so you get to use SQL like language. Okay. And so if you're like, oh, I'm familiar with SQL. I don't know how to use base R. I'll just install the deplier package and start using it as if it's SQL and start doing my joins the way I used to do in SQL. Then go be my guest, go right ahead. But I don't really use SQL that much. And so when I use deplier, I'm like, oh, my God, look at all this awkward syntax. And also deplier outputs a different kind of data frame. It's called a tibble. I say tibble, but it's actually spelled I think TBL like table. And I don't like how that looks. I like how the base R data frames look. And so I tend to do all my data management in R in base R. And it's probably because I'm all sassy because I learned SAS. And so that's why I wanted to hold this event today and teach you is I wanted to show you, if you're sort of SQL-y and you're like, I don't know how to use base R to do these SQL like joins, I'm like, I'll show you today. Because it's really important because if you don't do the joins right or the merge right or whatever you want to call it right, you'll drop records or you'll lose data, you'll screw it up. So I'll show you how to do it and make sure you did it right. But before we go on, let me take a moment to invite you to my free online workshop, application basics, adding analytics to pipelines. So if you're like me, like I was just talking about, and you're from sort of a healthcare background or more biological background and you do statistics and informatics, you may have missed a lot of terminology in computer science and in business systems. And you might be wondering, well, why do I need to know that? Why do I need to know about these things? Well, it's because nowadays, we're expected to analyze data coming out of those applications. And if you don't know the terminology, and you don't know how applications are designed, or how they store data, how data go through them, then you can be very confused if you receive some data set and you need to analyze it. So that's why I'm holding this free online workshop, application basics, adding analytics to pipelines. Oh, I see. Somebody likes base R in the chat. Yay, base R. I love base R. All right, so R is an application, right? And if you sign up for this free workshop, what will happen is I'll give you the Zoom links we'll meet on Saturday and Sunday. I say each group session is four to five hours. That's more like three to four hours. I kind of shortened it so you can have a little weekend on you. But what we'll do is we'll have, I'll teach from this online course, which is part of my core courses for my group data science mentoring program, which you can also ask me about if you're interested. And it's this applications basics course. So we'll be going off of that. And then, but we're going to be, it's a workshop, we're going to be doing interactive stuff. You can do some networking and talk to each other and come up with new designs for adding analytics to pipelines. That's our theme. So please don't hesitate to sign up for this free workshop. And now we'll go back to the regularly scheduled program. All right, joins in base R. Oh, and you want to download the slides, I put the link in the chat, because then you get these links to these two blog posts, but there's not, they're not just blog posts. The blog posts also have GitHub code. So like our code on GitHub, which I'm going to demonstrate. So you want to get these slides so you can go to this blog post so you can get the code. All right. So like I was just saying on the last slide, in public health, a lot of us use SAS, but some of us use Python and R. And so if you use SAS, you're used to merge commands, but in SQL, there's a join command. And so if you're not used to the join terminology, it can be kind of confusing about the different types of joins. But I'll sort of go over it. First, I'm going to go over the joins we normally want to do in public health. Like I'm going to kind of bias it towards our normal work in healthcare analytics. And then I'm going to explain like why you would do the other joins and when that happens. So the thing that if you're a SAS user and you're used to sort, sort, merge, what you're normally doing, even though there's more to the coding, is you're normally doing a left join. And so, and you may not realize this, but I'm going to explain it to you using actually NHANES data as an example. Okay. So if you go to that blog post, one of those blog posts, actually, I'll go to it right now. This NHANES data, so just quickly, if you want to know more about NHANES data, I already have a video on it I did a couple of weeks ago. But, and I'll post the video, you can find it on LinkedIn if you signed up on LinkedIn, because it was an event a couple of weeks ago. So in the NHANES data, just quickly, it's surveillance data, it's public health surveillance data, and it's available on the web. And it comes in these little baby data sets. Okay. So it's like epidemiologic like interviews. So the like ask them, you know, do you smoke tobacco and about exercise habits. And there's also examination data. And what they do is they unfortunately save all of these data sets separately. So there's a primary key for the, it's like a study ID called SEQN for sequence numbers. So that's like the ID, like if you're going to do sort, sort, merge, that's what you would be sorting on. And then in each data set, there's like hardly anything, there's like just a few variables. So what that means is you have to download a bunch of them and join a bunch of them together. Okay. And so what's happening here is the data set you want to start with is the demo data set or the demographics data set, because that has a list of everybody in the whole study. So that's probably going to be the longest one you have. Okay. And that's, the idea is each one of these data sets should only be like a one to one join with that demo. Like if I'm participant 183, I'm going to be in the demographics data set for sure once. But I may be in the smoking data set or maybe not. And that's the issue, right? So first, we download the NHANES data. And here I set the working directory for this working directory here. So I could demonstrate this. And then because the data are in SAS XPT format, I'm using this foreign package to unpack them. So this is the native data set is this demo here. This is the first one. So I'm going to read that in. And that's called demo A. So I'll just show you it a little bit. Like this is it. Actually, you know what I can do is just do, I'll do call names demo A. And that'll give you an idea what the column names are. So see, these are all demographics data. You know, here's the SQ, SQ, and that's like the study. All right. So I was working with some oral health people and I wanted to read in the dentition data, this oral health exam data, so called a dent A in that this is the native data set. So here we go. We'll read that in. And then if we want to know, here I'll just change this. I want to know the columns in it. We'll go look at those columns. Oh, look at all those columns. Yeah. There's like a column for each tooth. It's a tiresome data set. It's a pretty, I'm not very happy with the data set. But anyway, it's good for a demonstration, right? So you notice the SQN. So the issue is, let me just show you. So you know call names now. Now I'm going to show you N row. So N row is number of rows. So in demo A, the number of rows we have is 15560. So like 15,000 rows. Okay. But now let's look in dent A, right? So we know the business rules say, the business rules, that's a term you can learn in our workshop, say that dent A should not have more records than demo A because demo is everybody. You know, if anything, dent A could equal demo A, but it doesn't. That's the problem. So let's look at how many here. So there's only 13,000. So in other words, like we're missing, you know, somehow about 2,000 people didn't do their dental exam. That's probably pretty realistic. Okay. So why would I say we want a left joint? Well, the way it works is that I guess that people invented SQL read left to right. So the idea is, if you say two data sets in a row, like demo A comma dent A, then demo A is to the left of dent A. And if you say I'm doing a left joint, what you're saying is I'm taking demo A and I want to keep that solid and join on anything from dent A that matches. Now, if you do that, if you do a left joint the way I just described, what will happen is when you're done, when your merge data set exists, it will still have 15,000 or whatever columns, because it'll just have blanks here for anybody who didn't join who wasn't in dent A. Okay. And that's why they call it left joint is because the left side is forcing the right side to be that way. And if the business rules were broken, and I added like records to dent A that had SEQNs that are not in demo A, if I'm left joining, those won't join either. Like it's the one on the left that's like controlling it. So if you were the other way, if you went the other way, you were like, Monique, I don't care about who's in demo A. I only care about who's in dent A. Well, guess what that is? Well, if you put demo A first in dent A second, and you want dent A to control it, then it's a right joint. So I remember when my boss was explaining this to me, I had this boss who knew SQL, and I didn't know SQL. And I was like, I don't understand. I mean, there's this other concept of inner joint, which I'll get to. I understood inner joint, but I was like, how do you know left, right? He's like, it's the order you say the data set in. So obviously, if I'm doing this thing where I'm like putting the demo data set and then just joining on whatever matches from dent, I should do a left join and do it in that way. I should do this awkward right join and put demo to the right and whatever. So you're supposed to have like good programming formatting. Oh, hi, Suhaas. I'm glad you're here. All right. So now that I managed to read in demo A and dent A, I'm going to teach you a really important thing to do first is before you join this, look at this ugly data set before you join them together, first trim off only the columns you need. And this is a little trick I do in R that you can kind of do this in SAS, but it's easier to do in R. So first, what I do is I create a vector. I keep underscore demo, what that stands for. That's a vector of the variable names that I want to keep from the demographic data. Yeah, it is super easy in R. It's way easier than it is in SAS. In SAS, I think you'd have to make like an array or something. It's just too hard. I always have to look up SAS whenever I do something funky like that. But anyway, so all we're doing here, see the C and this is combined. And these are just words, like these are just characters. But if you go like if I do call names, demo A. Yes, you can use the calling numbers. Absolutely true. In fact, I'll demonstrate that if I remember. Okay, so here are the call names for demo A. So you see SEQN, but I did some sort of review of the literature and I decided I only wanted DM, DY, R, US, C, Z, which is one of these. So I'm just making this vector just say these two words. Like right now, it's just like a vector that says two words, these two things. And then this is also a vector that says the, so the reason I'm keeping the SEQN is that's the primary key. That's the index. Remember from SAS, sort, sort, merge, that's the thing we're sorting out. So we got to keep it. So I'm keeping, so these are just two vectors, right? Okay, now I'm going to trim. Like remember how I called this demo A? Well, I called it A for a reason. So I can keep advancing it to like B and C as I change it, right? So the, so let's look at the number of rows in demo A. It's just 15,000, we knew this. Okay, now see this trick? See this demo A and then these brackets and then keep demo. That's like secret code to R to just trim off these and put them in demo B. So I'm going to do that. And then when I do call names demo, see how lazy I might just go up here, demo B, we're only going to get the keep ones. Ta-da. Okay. So, and then what I like to do is I like to do an N row of demo B because why? We didn't want to drop anything here. I mean, we shouldn't have dropped anything here. But, and then here's number of columns and call is number of columns. So we see there's two, and oh, I put the column names down here. Okay, so we're going to do the same thing with dent A. I'm just, I'll just run it and see here, we just got these two. Okay. So now we have two skinny, two skinny databases or data frames. One is shorter than the other, like dent B shorter than the other. So now we're going to left join. Okay. So with the demo denominator and left. So, so what am I going to do first? This is just good hygiene is I'm going to do the number of rows first. Okay. 15, five, six. So I know we just did that. But, okay. Now I'm going to make merged underscore A. So what am I going to do? Well, I don't have to sort sort. Luckily, R is more recent than SAS. Okay. So I'm going to do merge. Then remember left and then right. So I'm going to left join. So I'm putting demo B first comma dent B comma. Then this is the primary key. Now normally I can put by equals and I can just put quotes, SQN, but it didn't work. I had to actually put the C thing. Like you remember how I did up here? So I don't know why I did that. Okay. But then here is the key. All dot x equals true. And that's your way of saying I'm left joining demo to dent. You can probably guess what would happen if we did all y equals true. That would be going backwards, dent to demo. Okay. So, but this all x equals true. So I, so big picture, we've got this demographic data set. We've got these other NHANES data sets that are smaller. We're going to be joining stuff on to it. We should probably keep doing a serial left joints, just to accomplish this task. So let's do it. So we have merge here and then on CQ. Okay. So now we're going to, so we know this is 15,000 on our left, the left data frame of our left joint. So we don't want to lose any records is 15,000, but we know dent B is only 13 something. So we want to make sure that our all x worked in merged A is the right life. So here we go. Okay. So this is the N row of merged A. Great. We didn't lose anything. And that's what was supposed to happen, right? And so now, if you were to look at, actually, let's just look at merged A. I don't know if you'll see, you see all these NHANES, these are NHANES from like this probably one right here. This is the end of the data set, you know, the columns. This is probably ones that didn't have a record in dent. So they ended up having NAs there because the left joint forced it. Okay. So now what I sometimes do when I'm doing joins is I'll add flags for whether it's in a certain data set or not. But this one wasn't a really good one to demonstrate that with because normally, if something's in a data set like dent A, there are values in it. But there were records in dent A that had no values in them. They like weren't filled in. So I was like, oh, so what I did to make a flag is I made a different business rule is I, so I created a flag called in underscore OHS. That was the name of the dental one. And I set it to zero. But OHS, IMP, that was a question of whether or not you have a dental implant. And one was yes and two is no, which are both answers. Okay. If they didn't say anything else besides one or two, I mean, that was the only variable I picked. Then if they said one or two, then they were in OHS. So we have their data. Otherwise, we don't. And so by adding this, but that's sort of a weird way to be perfectly honest, what I normally would do is I would modify dent A and I would just add a column that says indent, like in dental or whatever. And I make it just say one, like all of them. And then when they merged on, that one would be there. And the ones that didn't merge would be empty. And then I'd be like, oh, if it's empty, put a zero. And that's, and then each time, like here, I'm merging on the smoking variable. So I did this with smoke, the smoking data set. I just picked out a variable I wanted. And now I'm merging that on. See that here, like, I think you have to run everything or it won't work. Yeah, here. So now merged B has the smoking variable in it. And so what would happen is I'd have like indent, one, zero, and then in smoke, one, zero, whatever. And eventually I'd have all these flags and I could see if they was in all of the data sets. Or I could also like down here, remove some of them, depending on whether they like here, I'm saying box one is merge B, this is to evaluate selection bias, because that's the problem with this data set. But anyway, I mostly wanted to talk about these merges. Now I'm going to go on, if you have any questions, you can put them. Oh, I was going to talk about column numbers. One of the things, let me go on here. So let's see here, call names. And, okay, so I'm just going to run this. Okay, see this one here. And see how it says Seqn OH, OHX, IMP. This is this is column number one. And this is column number two. And let me actually, let me do this on dent A to sort of show you what the, okay, see here, like, see how this says seven. This is actually the seventh column. Okay. It's really cool. So in SAS, it's a lot easier to automate things by using variable names, right, like you make arrays of variable names, not their positions, right. In R, I found it easier to automate things if you use the actual column number. It's just sort of hard to get the syntax right a lot of times if you're doing like functions and stuff, and you have all these quotes. So what you can do is there's, I don't have the code for it, but there's a which command, not like which like boil, bubble and toil, like which one of these, the which command that you can run on say like which is, which column is OHSO5CSC and it'll return a number. And so what I'll often do is run this which command and get a number and then use that number in my automation. And I run the which command just before I do the automation because these columns move around like you can tell I've been moving them around a lot, right. Oh, and Austin points out that grep is pretty good too. I found that grep is, I don't know why I've had better luck setting values with which. I think I've had better luck automating other things with grep, but you know, I'm not that good of a programmer to be perfectly honest. So I just use whatever I can get it to work. But yeah, so, but if it's like imagine that I say, okay, I care about this variable, which is happens to be 67, 68, it happens to be variable 69 right now. Well, if I use this name, it won't, it doesn't matter whether it's 69 or two or whatever, it's going to get the right one. But if I use this number and I hard code it, then, and then I change sort of what I do, it might be grabbing the wrong one. But what I can show you is that you can do, I don't know how to do the merge code, like, I think you can, I'm not even going to try it because of course, if I'm going to program in front of you all over, but I can show you a little bit about how to use these, the numbers. So, so it's not only columns that have numbers, it's rows that have numbers, as you probably guessed, right? Like in SAS where they have the OBS, you know, this has, it's called row names. So if I do dent A, and I just do, so it's row comma column. So if I do like one comma one, I'll get, I think probably the first SCQN in it, right? Yeah, that's the first SCQN. It's row one and column one. But if I just want the whole first row, I can just make this empty and we'll get like, yeah, see, here's this person's like teeth measurements. Or if I just want the first column, I can go over here and get rid of this and just make this empty and do like this, right? And see, that's all the SCQNs. And you can do all kinds of fancy things, like I can say this is row one to five. And I just want columns four to 10. And I've got that. So that's sort of how you do that. And that's makes it really cool. Let's see here. So we have a note from Austin who says, Grep is amazing. This is what I love about base R, the row slash column referencing is so straightforward. Oh my God, yes. So thank you, Austin for pointing that out. Part of the reason why I don't use this supplier is because I like using this terminology that I like being able to switch between the column, the numeric column and row notation and the names. But I'm a little confused about the Grep because where what are you specified? Like you're looking for ABC or XYZ, or you probably have a whole thing in there. And then value equals T, like what is the thing you're searching? Like is it a data frame? Or like, I don't know. See, that's what I get screwed up with Grep on. And so I always end up doing witch, but now I can't even remember how to do witch. So probably not the best programmer here. But I wanted to quickly sort of go over mistakes that you can make using base R and you can screw up your joint. So the first one is that, so this was the correct left joint. So first, using good hygiene, you put your denominator, like the longest dataset or the dataset that you want to not screw up. Like you want the same amount of rows in the results. You put that first on the left, and then you put whatever you're right joining on on the right. Maybe it's in there, maybe it's not. And then you say all X equals true to tell R, that's what you did. You put this one on the left on purpose. But here's the first mistake you can make. Instead of all X equals true, all Y equals true, then you're going backwards. So here's demo B, we know that this is 15. Okay, now we're going to merge dent B onto demo B. Okay, so we're going to make that, we're going to use all Y. Okay. So notice, remember how in dent B, there was only like 13,000. And because we use all Y, it dropped the records from demo B that weren't matched by dent B. Okay. And so that's a problem, right? And by the way, this is kind of an awkward thing to do. If you really wanted to do that, you should probably do a left join, put dent B first and demo B second and use all X. That's basically what my boss was teaching me is like, right joins are weird, like just don't do them. Just do left joins and be clear about it. Okay. But you can try to do a left join and just screw it up. And how you can do that is have your all X be right, but the data sets in the wrong order, right? So if I want to keep demo B, but I accidentally put it in the wrong order, I'm going to end up with the same problem where demo B is 15,000, but my merged A is only 13 something, right? Now here is the problem that people tend to have more commonly is that they just forget this all, all X true or all Y true thing altogether. They just say merge demo B, dent B by SEQN. And that's called in SQL and inner join. So that's only going to join the ones where they're both equal. Now, because there's a one to one relationship by our business rule in here, what this is going to end up doing is just getting us the 13,000, some right. Now, what would happen is if this was a more complex data set, like there were, you know, this was like maybe patients and encounters, right? So there could be multiple encounters per patient. What you'd end up doing is just keeping patients who have encounters. So if there were patients without any encounters, they'd be kicked out. If there was encounters that were often they were connecting any patients, they'd be kicked out. And this is often the mistake that is made when people are merging. They want to do a left join, but they forget this all X thing. And then they don't do it. So in public health and biostatistics healthcare, we often have data about enumerated experimental units like people or hospitals. And they're like entities. So if you from informatics, each time you have a table, the primary key is about an entity. So if you go to a car dealership and you say, what cars do you have available? And they have a table of all the cars available. That's the entity of that table is car. And so we want to join on or merge on attributes from other data sets. So like the cars, like let's say there's a four door two door car, you know, that's an attribute of the car. So but there might be other attributes of these cars like their vehicle numbers or whatever. And you'd want to merge those on from other data sets. So we're concerned with assembling a full picture, like a full row of data about each individual in the data. So let's say I have a list of hospitals in Massachusetts, and I'm joining things on maybe I'm joining on information about like the county, the hospitals in our county population or anything like that. And I just want to fill out this row of information on these hospitals. But that's mainly what we do when we're doing like biostatistics. And I guess I should say epidemiology because our epidemiology is always based on these individuals, right? But other things, other uses of sequel type joins are happen a lot in data warehousing, which I also do of health data, right? So let's pretend that Anaheim's data set was a mess instead. And there was like duplicates in healthcare and like claims data, like insurances, they often have duplicate claims because like somebody will submit a claim to get paid and there's something wrong with it. So I have to resubmit it. So you have to, so these joins can be helpful in deduplicating. And you can use them strategically. You can also use them, especially if you read that other blog posts, you use them to understand overlap between data sets. So let's say you have a list of patients from one place, and patients from another place, and you have like their social security numbers or something, you can use these different joins to figure out like the Venn diagram of what patients are at both places. And also, a lot of times people use really complex joins and they don't do something simple like I just did in R. They'll have platforms that are doing joins or they'll like have software that's doing all this for them so they can look at it and make sure they're not doing it wrong. And often they're doing that to create like huge data sets for training AI, you know, artificial intelligence, like they're kind of piecing together like transactions and stuff like that. So there's a lot of like, I don't want to undersell the sequel programmers of the world. You're amazing. But I'm not one. And so I'm going to use base R. And I'm going to do my sequel like joins using my base R and my options in it. All right. So thank you very much for coming today for my talk on sequel like joins and base R. If you weren't here in the beginning, I just want to remind you that I want you to sign up for my free online workshop. It's Saturday and Sunday, December 16th and 17th. It's on Zoom. And the title is application basics. And our theme this month is adding analytics to pipelines. So if you're like me and you were trained in healthcare analytics, you often were not trained in computer science or the background of how applications are built, how they're designed, what they actually are technically. And so I had to learn that all on my own. And the reason I did it is so I could be better at analyzing data from applications because you kind of have to understand them if you want to analyze data from them. So if you want to analyze data from applications and you want that background and you don't have it, please sign up for my free workshop. It's on Zoom. It's based on an online course from my group data science mentoring program, which you can ask me about if you're interested. But you get the course for free and we're going to do all these interactive things. So it's like really a workshop. You get to network and interact with people. So everybody look in the chat, Austin said call names, parentheses, dent A, and then you've got the brackets and you've got the grep command. So, and as Austin explained, this grep, so the pipe in the grep command is an or, right? And I believe you could probably use an ampersand for the and, you know, if you wanted 11 and 12 or maybe even a colon. So this is in the scenario say that you would know that you're looking, oh, this is columns 11 or 12. So if you're looking, if you know 11 or 12, it's like you're looking at columns 11 or 12, right? Or yeah. But you know, in any case, what you can do, what I often would do, maybe I should do, I'll do something on the witch command, is I'll use the witch command to figure out which is the position number of whatever column I want. So it doesn't matter what I did. I ask it that and I put it in like, I'll call it like if it's OHXDent, I'll say OHXDent underscore pause for position. And that'll be a number. And then I'll use that as a variable, like in that grep. Like I'll use the variable name instead of the actual number, because then I know the number's right if I do the witch first. Yeah, I, oh, column names with the string 11 or 12. Okay, that's what I was saying, the column names with the string 11 or 12. But again, so how would you do it if you wanted to use grep? Well, you just Google for grep and you look for, in fact, how do you do it if you want to use witch? I always Google for it and I always find something on stack overflow. So that just shows you how much of a programmer I am. I'm stealing people's code from stack overflow. But in any case, I agree with Austin, base R gets the job done. And so you can certainly, as long as you're paying attention, do your merges properly in base R. All right, well, thank you so much for showing up today. So I could talk to you about doing SQL Lake joins in base R and how to do your end rows to make sure you don't drop any records, right? And please strongly consider signing up for my free online workshop. And we'll have a nice weekend together. And so thank you for showing up today. And I hope you have a good week.