 Cool. Okay. Right. Shiny. So I'm Chris Beely. I'm a data scientist. I work in the UK as you can probably tell from my accent I work in a trust called Nottinghamshire healthcare NHS trust I work in NHS, which I think is the largest provider of state-funded healthcare in the world What's only one of the largest? I'm sort of known for shiny amongst other things hence why I'm here So I already said all this bit at the beginning. So I just said that before we started Basically, we're going to do just two of the three sessions today. Do look at the session three in your own time on the GitHub It's all there We're basically going to we're going to build something very very very very very simple ridiculously simple So you get the idea of it and then once we've done that we'll build something a bit more complicated and we'll look at some of the more advanced techniques and I might just quickly summarize for you What's in session three just so you know kind of what's available and what's possible and what kind of thing So what is shiny I think that's the first thing that's worth saying obviously shiny is the thing that you build dashboards And I'm sure nobody is here who doesn't know that But the thing that it's important to understand about shiny is that it's it's a web application programming framework So whether you know it or not you are writing HTML JavaScript and CSS So as you write our code that our code itself will produce Various bits of JavaScript and it will all be seamlessly kind of tied together It's worth knowing that because what that means is that you can actually mix HTML and JavaScript and shiny together And I don't have time to talk about it today, but on an advanced shiny course I might tell you about Actually shiny is pretty good allowing you to kind of have a little of each it sound when you first hear about it Sounds like it'd be very complicated and shiny be very strict about saying this bit can be a you know All that kind of thing, but actually it's not you can mix them very very very freely together and that gives you quite a lot of power So if you do know Web technologies HTML JavaScript and all that kind of thing then you can do a lot of stuff For example, there are things that are easier to do in idiomatic JavaScript than they are in shiny So JavaScript experts and I don't count myself amongst their number. We'll just write pure JavaScript for that bit Okay, so what a shiny do you probably seen examples of shiny this is the this is the hello shiny thing This is the thing that comes with the package This is the most simple Application that there is and it demonstrates the principle is shiny where there is an input over here on the left I'm assuming you can see my mouse pointer and there's a there's a graph over on the right and You'll see that every time we move the The thing on the left the graph response and that Basically is the fundamental sort of way that shiny works that's that's the fundamental principle is that when inputs change outputs change and it gets More and more complicated the more and more shiny you do But you never really get away from that from that basic idea that when inputs change outputs change Yeah, and it always does this every single time is I don't know why but it crushes my web window when I interpret this Let's just refresh Okay, but shiny does obviously lots of You know it does simple things but also does lots of very complicated things So some people build kind of great sort of statistical type applications in it obviously Drawing on the power of R to do all that kind of data crunching back-end type stuff and people also use it for all sorts of kind of flashy Web gizmo type things. So this thing over on the right is a map drawn with an R interface to JavaScript library called leaflet and this application actually rather nicely illustrates one of the One of the nice features of shiny which is that you can get the the different outputs to interact with each other So you can see this red point over here on the graph on just towards the top left Is this point over here on the map? And that's you can there's a library that allows you to have cross talk between the outputs And again, I don't have time to talk you through that But I just thought you might find it interesting to know that those are some of the things that you could do It's all just it's all just web technology. Basically. That's how it all works I just noticed I've got the chat up. So I'm just gonna pop it so I can see it Okay, right, so how does shiny work so this is the thing that you need to understand basically So this is the thing I'm gonna be driving home in this first session So shiny works using something called reactive programming And reactive program is not unique to shiny. It's like a thing that exists elsewhere And it's that thing I mentioned already. It's the idea that when the inputs change the outputs change That's that's basic shiny In the language of shiny what we say is we say that the outputs take a dependency on the inputs So in this simple example that we saw here This graph on the right takes a dependency on the unit on the left and it's all done automatically I'll show you how that works in a moment but you don't have to tell shiny that shiny just knows and Because shiny just knows That dependency is set up and because that dependency is set up when the inputs change the outputs change And that that's shiny in a nutshell So just for those of you who I hadn't done much programming before I came to our either so for those of you who were not kind of Oh fail with other programming languages just might be worth just mentioning It might not seem like a very important feature that But in fact if you look at other programming languages So for example, Java and I was actually writing some Kotlin I'm trying to teach for self-android development. So I was writing Kotlin Which I think is quite keen to Java over the weekend and It doesn't do any of that stuff for you at all So it doesn't doesn't set up a network dependencies automatically and the outputs don't automatically change when the inputs change You have to do all yourself. So you have to laboriously go across the application and explain to the application What does what? Which is fine. It's not difficult, but it's just a lot of boilerplate code It's a lot of work and of course the more you write and the more you do the more likely you are to make a mistake So shiny just knows that all for you The downside of that shiny is that that precise thing that it does it all for you So sometimes I have a great friend actually who often sends me weird things. He's trying to do in China that shiny doesn't really want to do Shiny kind of does what shiny does that there are ways of kind of tweaking it slightly But it because it because it works automatically that can sometimes be annoying and it can do things that that you don't want it to do So for example database applications what's called crud applications. I can everyone what it stands for create Something update and delete I think That can be quite hard There's loads of you'll find loads of people talking about this on the internet because people often want to build databases and shiny Because the data can disappear before it's been uploaded to the database Shiny is not I mean it's possible lots of people have done it But it's not a very natural way of writing a database because shiny to take it takes too much control off you It takes it puts its hand on the steering wheel in an unhelpful way. There are ways of controlling the reactive dependencies Which I will just briefly outline later, but again in a three-hour course We don't have time to go into details of reactivity, but just so you know that although shiny does do everything automatic You can actually give it a bit of advice and say no, I don't want you to do that And there are various ways of trying to control Kind of tame the beast if you like So just a very this is becoming increasingly more of a historical note really to be honest But I guess you know code never dies does it as we all know So I'm just want to mention that back in the day when I started using shiny We actually used to there were two code files one was called server you are one was called you are now that way I think is dying out now it lives on in the in the wizards for shiny as I'll show you But for example, you have the weapons bookmastering shiny. It's totally absent. I don't think that there's even a reference to it At the same time more advanced things like golem which I use which again I don't have time to talk about but it's very interesting if you're interested Does have a to file approach so we're having quite settled but anyway Basically my take on this is Hadley Wickham does single file. Who am I to argue with Hasley Wickham? I'm gonna do a single file. So that's what I'm going to show you But I just want you to know that if you see things on the internet understand what they are It's the same really it's just one code file had the one bits in one file and the other and the other one Just has them both stacked on top of each other. It's the same code. It doesn't change the way the code is It's just where it is situated So the server bit of the file is That's like the sort of the guts of the applications That's the the data processing and the statistics and the graphs anything that it's being done to the data Will all be done either in the server bit of the app file or in the server to our file and the UI file is The how it looks so it'll lay out all the buttons and widgets and graphs and tell everything where it's put It's worth noting in passing that the UI Section is run once and only once and then never touched again, and I'll talk a little bit about why that matters later on But it's just useful to reason you understand when you're designing applications when you're debugging and when you're looking at where data is The UI is loaded first and then it's never touched again So that means that you can't do some things in the UI file You have to have a bit of a work around which we will talk about later, but it's just worth understanding that Right, so that's it. So that's how shiny that's what shiny is that's how it works. That's how you write shiny So now we're gonna get to the more kind of nuts and bolts of it in terms of what you actually write and So essentially and I'll show you all this and I think it makes a lot more sense when when you're shown and the shiny widget does A nice not which it's very wizard does a nice job of kind of laying out the boilerplate code for you Basically, you define inputs obviously your application is going to need to have inputs There are lots of different types of inputs that all have separate widgets Is it possible increase the size of shared screen? Yeah, that's a point. Yeah, that would be good Yeah, maybe is oh, yes there Yeah, sorry, I sort of saw that and I didn't know you go Yeah, so you've got the inputs and there are lots of different types of inputs like those text inputs and numeric inputs All that kind of thing and they're they're produced with code that looks like this say text input and numeric input And you give them all names and then you lay out the Outputs of the applications are the graphs or the tables or what kind of thing and they all have names And then in the server file that uses the names that you've defined in the UI thing to say You know this table accepts this input from this place and it mixes them together and does some sort of calculation Outputs this And then your UI then lays out those outputs on the screen And that's it basically so it's a set of widgets that Receive data. It's a set of widgets that output data like you know plots and tables And it's something in the middle that kind of mixes it all together with the names that have been defined To show you how it all works Right, so I'll show you so if you just follow along with me So I'm going to reshare my screen now. This is where I get in a model with this course Because I end up with 15 million windows open So just bear with me a moment share screen I've got a startup idea that it must be an easy way to this You know people who teach online there must be a market for like making it really easy to kind of Show lots of things because I constantly stroll with this, right? That's it there. This is my shiny. This is my RStudio window So I'm gonna make the text bigger that's first thing I'm gonna do because otherwise you won't be able to see it And I'll get rid of that I'll get rid of the extra column because that's not really helping us great, okay, so I'm going to show you how to How to start from scratch basically and I would highly recommend that you when you start from scratch you always use a template don't Don't kind of type in I don't know why you would do that anyway But don't because if you make a mistake early on then you'll you might never be able to find it So it's always nice to start with something that works So that's what we're going to do. So if you just go to file and then click new file and It is Shiny web app Just here. Oh, I tell you what now. I'm sorry. I'm going to get a model on that because This is also the training So I'm actually going to share a separate window I'll share a blank RStudio window. Oh, yeah, sorry about that. Okay. Let's start again Probably just show my desktop Cole, okay. Oh Yeah, extra column. Yeah, I live and I live by the extra column, but obviously it's not not great in workshops Okay, so we're going to file new file and we're going to go to shiny web app And just click that and Then it's gonna bring up the wizard and this is where I mentioned that the multiple file single file lives on So as you'll see single file is selected. So we're gonna leave that selected So we just Just put this anywhere. It doesn't really matter. We're not going to spend a huge amount of time on this anyway It's just this is to illustrate the very basic simple principles. So I might just call it test app Create it when whatever director you want to and then just click create and here it is I wonder I suspect the text one. Maybe I'll make it one one bigger So this is What you will then be looking at so as I say I highly commend that you do this forever. Don't ever Not use the wizard There's some sort of Rubbish at the top. So for the purposes of the workshop, I'll just get rid of we don't really need the library shiny call either one we're using our studio because It'll be loaded automatically. So we'll get rid of that top just so you can see a bit more clearly what I'm doing Sorry, my cats just come to join the meeting So here it is so hopefully you're looking at something that looks like this now If you're struggling then do as I mentioned, you know in the chat. So this is This is the basic shiny application. So if I just press run app now It'll appear sorry, it's popped up around the monitor Here it is. So this is the thing that we that I showed before on the side. So this is This is the hello world application as you can see it does all this I could do before So let's just have a look at how it works so This first bit here at the top. This is the UI. This is what I mentioned was that was the layout Now nearly all nearly all in fact, I think all shiny applications will start with fluid page Once you get good at shiny you'll start to be interested in why that is and but it's not terribly interesting at the beginning So I'm not going to talk about it But that does a lot of homework basically it does it does a lot of setup for you that will be invisible to you unless You start thinking more deeply about this And then it's it's just put together with a few more bits and pieces. So there's the title panel Command that will make a nice big title at the top left as we saw before And then there's only one more function with some more functions inside it and that function is sidebar layout So sidebar layout will be your friend early on when you're learning shiny because it's the most sort of generic vanilla Out-the-box type of shiny application that there is So perhaps I'll just bring it back up again. No, that's the wrong window again So I'll just Just bring it back. So basically The sidebar layout what it does is you can see this is a title panel up here The sidebar is it gives you a big gray box down the side that you can sort of type You know put stuff in put widgets and date selectors and whatever else you want Well, the inputs you want and there's a big blind carrier over here for outputs Now it's not to say that you have to put the outputs on the right and the inputs on the left You can put them where you like But the nice thing about this layout is this is a sort of this is what your users will be expecting to see So this is a very natural way to write shiny applications So as you're learning you'll probably will just put three or four input widgets here And then something here and we'll talk about what those somethings can be in due course So that's the layout And as you can see that the layout is actually itself composed of two things One of them being sidebar panel Sidebar panel contains all of the inputs. There's only one input in here. It's this thing But you can put loads of inputs in there and we will do that in a moment And there's another argument which is the main panel function and the main panel function It lays out everything that's on the right So this thing basically this thing here says I want to use a common-agard shiny app framework And then shining will say okay, what's on the left put it in sidebar panel and what's on the right put it in main panel And that's how it's all put together So now you understand that the layout the next thing to explain is How it all gets stitched together. So you'll see here This is the first argument to us to to an input is always the name the name that you're giving it So this is that the name that the R will use throughout to understand what this what this is The second argument is always the the user readable label So you can see obviously we've got a very nice computer rename here With no spaces in their punctuation and we've then got a nice human readable label here These are the arguments I won't go to them in detail because they differ depending on the numeric input I'm just trying to talk about the principles at the moment. So you give it a name you give it a label And then you'll see What we go down to the server thing that that name allows it to be referenced inside the code So if we come down here, you can see it's here And what this is doing is saying Whatever is in inside this input here I want that value to be in here. So for example, this value might be 37 In which case that would read 37 Similarly this label here, this is another human label that we've assigned Is is a reference here in the server file. So the server file is where you among sort of things Define the outputs So the output is defined by this by there's a set of functions depending on what the Particularly type of output you want is and we'll look at some of them as we go through This one is a render plot because we want it to return a plot You do have to get it right. Otherwise shiny doesn't even fail with an error message. It just doesn't do anything um So yes, so in order to reference Here so when shiny goes here will say well, what's in here? How do I know what to draw? It will go to this thing called output dollar sign. That's how all the outputs are defined output dollar sign and then the name So it'll go here. It'll say what's in here. It will go to the server file It will say oh, yes here. It is output dollar sign this plot. What's this? It's a plot How do I draw the plot? I do this at anything inside With an input dollar sign is a is an input up here So inputs are defined basically with input dollar sign and outputs defined with output dollar sign um and The last thing to note about this application is This is how the reactivity works. So I mentioned at the beginning that um, all these are defined automatically So you can you can hopefully see that here So the reason why shiny knows that every time it updates the value of this bin thing It should redo the plot is because it's referenced in here So that shiny will automatically see that and say well that value is in there So every time that value changes logically this graph will look different So therefore if the graph looks different, I should redraw it And that's how it does it so you can have as many inputs here as you like And as many inputs as you put in it will form dependencies with all those inputs So if you've got five inputs all referenced in here The graph will redraw every single time any one of those inputs refreshes Now that can be unhelpful, which we'll talk about later um And yeah, and this this just basically runs it as to say it just leave us alone You don't need to think too deeply about what's in there really. Um, you're only really interested in updating what's in here And what's you know in in between this bit here It's very interesting all this stuff on the outside, but it's not worth bothering about when you're still learning Right, so I'm not saying anything in the chat. I'm assuming everyone's happy with that I might just recap actually I think that can be helpful sometimes So just just to very quickly recap the ui Is made up of this fluid page thing Which does a lot of clever stuff in the background that you don't need to worry about too much It's got a title panel, which is a nice function that would just put a big block of big text at the top left It uses one of the built-in layouts the most common one the sidebar layout Uh, which I would recommend you write all your early stuff with although we look at other stuff later um And that sidebar layout has got two things in it a sidebar panel containing all of whatever you want on the sidebar panel Which will usually be inputs but doesn't have to be And a main panel which will contain all your outputs, which will which will which will contain everything that's on the right Which would usually be output, but it doesn't have to be We name the inputs And we name the outputs and by doing that it allows shiny to understand This output can be drawn by looking for this output dollar sign And this value here can be referenced by looking for input dollar sign And as I mentioned the reactivity is automatically set up because of the way the codes are written because this is referenced into here It's also my favourite one Okay, cool, right that's that let's go back to the slides. Um So let's just stop sharing and uh And I shouldn't I'm just going to share my sorry. Yes. I need to get better at this I'll just share this up to and just leave up and just put whatever I want to share on there. That's easier, isn't it? So My computer doesn't seem to be very happy today. Which is not really helping Okay Cool, right. Yes, I've talked to all that that would normally be behind me when I'm when I'm talking this in a workshop But unfortunately we're not in the same room. So I can't really do that um Oh, yes, and then we're going to do we're going to do a little exercise now. So take the application that you've just um The vanilla one that we you've just sort of loaded with the wizard. We're just going to make a very very very tiny change to it um What we're going to do is we're going to add a title To the graph and you can type the title in the box on the left So we're going to define a text input over on the left on the sidebar panel and Uh, we're going to allow the users to type whatever they like into it and whatever they type will appear um on the above the graph So that's what we're going to do now. So as I mentioned before if you if you feel like kind of just Jumping in then please just ignore what I'm saying. Um, but just to keep us going and to help those who maybe um Might get a bit lost otherwise. I shall just demonstrate um So in order to do this we are going to um, firstly, we're going to add an input and the input is um, let's just have it straight underneath the first input and It looks like this So as I mentioned before the first value of inputs is always without fail What r is going to call it? So let's call it title. That's a good name for it And the second value is always what your user will see So let's write a nice friendly thing. Please add a title on that um And that's all you need So that will add a little box over on the left that people can type into um having done that we're then going to add it to the um To the graph that's drawn down here I don't know if people really use uh base r plots anymore So I think it's a kind of a bit of a funny example I think this now really because I often teach this And I think there are quite a lot of people who come to the shiny course who've never used the hist function their entire lives um So um Yeah, I think that's a bit weird, but maybe they'll well it's dependencies. I suppose and they don't want the dependency anyway so Just to make the point For those of you aren't familiar with base r the way you add a title to a base r plot is with this main argument And as you can see it says here um What the title is Histogram waiting times So we're going to get rid of that. We don't want it to say that we want our users to be able to say what it is So let's just get rid of that And instead so as I mentioned before we can use the import dollar sign notation like this And it's just the the label that we gave off here. So it's just title I do think that's rather an obvious point this but I do find it a good idea. It's a copy and paste Labels rather than typing them because shiny is very difficult to debug as I'll mention briefly later So whatever you can do to avoid silly typo bugs is all to the good because it can be very difficult getting stuff out sometimes And that's it. I hope so if I press run now, well, I think I need to stop it first because I think it's still running So press run again And here it is please add a title and if we type in here um We can uh, we can see hopefully That it works Something else just to mention in passing as you'll notice that every time I touch a key It changes That can be difficult sometimes if it takes a long time to do the processing Sometimes it can be good to kind of slow the application down a bit Um, that's something else. I don't really have time to talk about but it's something that's uh Worth knowing about that you can get shiny to just wait to see if the inputs have finished updating um Before I only see hover details output Hmm. I'm not entirely sure what that means. Um Yeah, I'm sorry for that. I'm not sure I entirely understand the problem you've got there. So this is the base on the wizard Uh, we've added a text input here And then we just added main equals input title and you should find the application then will have a user definable um user definable title Yes, but do I can come back to that if you if you still have any problems Then just just let me know in the chat. I'll keep going for now, but I can come back to that Okay, so hopefully you all done that successfully. Um That's what looks like that's the answer. That's what I just did. Uh, I'm not seeing anything in the chat So I'm assuming you're all happy So that's it. So well done. So you've you built essentially from scratch with the help of the wizard your own shiny application So you're well on your way um, so having on that let's uh Let's make the whole thing. Let's use the wizard to build the framework But then let's get rid of all the middle of it and let's let's build it all the way from from scratch so, um This is the bit where I explain the course layout to you. So let me just get my R window back again. It's over here So many windows So as you'll see, um There are there's lots and lots and lots of code files in here um It's provided part. I mean it's partly to help you on the day But it's also partly I provide all the stuff with the intention of helping you to do it Yourself if you know what we don't get to and if you get stuck or whatever Or even if you don't don't come on the course at all and you just want to just run it in your own time um So basically the way that this all works is like a common naming convention. So We're going to look at something called sitwrap first So that implies two things the first thing it implies is that um There'll be a folder called sitwrap first now that folder contains the answer So if you get stuck or you you know want to know how to do it or whatever that's where it is So that's up here from getting stuck But the other thing that it contains also is a file is a file called sitwrap first r That is not the answer. That is the code that you need to make the answer. So that's what you need to um So get started with it. So that is just a sort of collection. It's not a shiny application It's just it's basically a load of it's mainly server code. I'm giving you the server code because I don't It's hard to teach shiny in a way because obviously you're trying to teach people dashboards But you can't have a dashboard with nothing in it So what I'm doing is I'm giving you shiny to output code that does something and then we're going to learn how to Put it together between ourselves um So that's what all that is Um, right. Okay. So as I say if you're feeling comfortable and confident confident, then please just crack on and just ignore what I'm saying Um, but if not, then I'm just going to just work through it now Um, oh, sorry. I haven't demoed it yet. I need to demo it first Other way you can't you can't build if you don't know what you're building. Can you? Sorry. Yes, of course Here we go. So here it is. Here's what we're going to build. We're basically going to build Uh, this is uh, this is like a health example. That's where I work a work in in health So this is just an example of the number of people who came to different teams I've given them a mangled all the names because people don't like details being published on github But there's a there's a big table Uh, that lists by month the total number of people each Who coming to the service in that month and these are each of the individual services And the training isn't going. Yes, absolutely. Um, it would have said that in the email Um, I'll just I'll just pop it in the chat for you. Oh, yeah, there is someone's not in front of me. Thank you. Um Yeah, so that's that and also, uh, there's a graph and the graph does much the same thing It just summarizes the the the monthly attendance for each of those services with funny names over the time Um, so that's what we're going to build. Uh, we've got some filters over here Yeah, we're going to filter by year I'm going to filter by status that status is like did they come? Was it canceled? You know did they cancel it? Did we cancel it all that kind of thing? um And it uses The code in the example so it uses this data So you can just live this straight off github It uses these packages And uh, oh, sorry. No, this is just the answer isn't I'm supposed to be showing you the exercise. Yeah, so this is the data and the packages This is the server code verbatim. You can just pick my idea is you can just cut and paste this straight And so I don't want you writing server code because it's just just too many things I can go wrong um But this is something that draws a table Uh, and this is something that draws a pot I'll talk a bit more about tables in a moment when I'm going through it Basically, this is the table code and this is the um The plot plot code and those are the the ui function I've just put some examples of the ui functions that you need you're going to need to select input Which looks like this this thing here where you can select the different values um and there's a There's a dt output. That's the type of table output and there's a plot output. Obviously, which is where the plot goes so yes with that So with that example code and with the wizard we should be able to build an entire application that does that from scratch I will almost certainly make at least one mistake But I'm sure we can roll with it Um Just get rid of all my nonsense. Um Um Right, so let's start again. So we're going to um, we're going to start another um shiny application. So same same um procedure So we're just going to go to new file oopsie daisy And then we're going to go to um shiny web app Um, again, obviously you can put it whether you like Uh, let's just call it sit wrapped first since that's what it's called on the slides um And we're going to make a single file app. I mean, I do have lots of opinions about this single file dual file thing But this is this is not the not not the time or the place Um, let's just get rid of this go into the top because we don't need it just gets in the way the workshop um So I'm just getting rid of my nonsense from other sessions Um Right. Yes. So here we are. So this is the this is just the the same applications again. So clearly we don't want this Um, I would recommend this is obviously a slightly unnatural way to build shiny applications You don't normally get given all the server code. However, I would argue it's not super unnatural. So for example Particularly within my teams and most people will they don't really know shiny. So they'll they'll write our markdown And they'll send it to me and said this is our markdown. Can you kind of make it interactive with shiny? So I'll just pull out all the you know all the aft bits from there are marked down Stick it in shiny and then kind of just wire it up So we're doing a process that's kind of similar to that um So First thing to do is let's just get rid of all this server code. So we don't want this get rid of that And we're going to replace it with the code that I mentioned here It's called sit wrap first r and it's in the um in in the folder um So this one can just copy straight verbatim Into the application like that This is a table And this is a graph So having done that Uh, the first thing to notice is obviously these outputs are not defined anywhere. So shiny has got no idea Uh, what output table is so it won't draw it and ditto. It doesn't know what output graph is either Well, it doesn't know where it is. Sorry. So it won't draw that either So that's the first thing we're going to change So let's do this from scratch. Oh my slack's buzzing away the corner. I'll just shut that down So we'll just start from scratch. So We need, um Two selectors basically. I've still got the shine application. Yes, here it is. So we need a year Um, oh, sorry. No, I'm not I'm doing outputs on. I'm sorry. I got confused. Yes. It's like confused me table and graph So we're going to go Here So the first one is going to be a table Um, which is uh dc output Is that the wrong function? Let me just check. I don't want to go the wrong wrong function Where are we? Where's all my windows gone? There it says yes. Yeah, that's a dtm point. Yeah And then we're just going to give it a name And we've already got the name because it's defined in here. So again, this is a little bit artificial, but you get the idea so That tells us to say well, how do I draw this table? Oh, it's just here Um, and then we're going to uh have a plot So that would be the plot output function I'm going to give that a name and we also again in a slightly unnatural fashion have this Name to it is called graph Okay, so that's the server code added and that's the um That's the main panel redefined to have a table on top of a graph um So well, let's just run it just for this just For fun just to say it's not going to work because we haven't done the inputs yet But let's just have a quick look. I could not find that function dt output. Oh, yes. Apologies. That's my mistake Of course it is because I didn't copy the um, I didn't copy the library code in did I? So the library codes up here So you're going to need to copy that across otherwise it won't work I can just go right at the top Um, oh, let's put the data in while we're at it. So this will also load the data right straight from github Like that right now. Let's see what happens when we press run yeah, so, um It does run. I didn't think it would actually be honest. I thought it was crash But it does run but obviously we haven't set the inputs up properly. So there's nothing it's not working Um, I wonder if there's any error messages in the in the control. Actually, let's just have a quick look to see if there is No, there isn't. Yeah, that's a kind of interesting illustration. That isn't shiny. I mean, I love shiny obviously, but shiny is very good. Um at Not giving error messages when things are going horribly wrong. It just marches on um Yes, it's shiny contact just today. Yes, it is just it is just a data frame. It's not a reactive object We're going to talk more about the difference between reactive and non-reactive data sources In due course, but for now, we're just loading in a totally static object and we're just going to interact with it in shiny um Right, so that's the first thing you want. So we've laid out the um, we've laid out the outputs We've defined the outputs. So all we've got to do now the only problem that shiny's got now is it doesn't know What all these things are it doesn't know what input year is it doesn't know what input status is either um and uh In order to define that of course, we're going to have to um, we're filtering by these two things. So this is obviously the year And this is the status so, uh, I'll just load in the um the um The data so we can just have a quick look because we need to understand what the data looks like in order to write this so It's where are we shiny training Oh, no, I can just start it from getting myself. I'm doing it. I like you do that. I can do it myself Beautiful So here it is. This is what it looks like So as you can see there's a year variable That's numeric Just a year obviously And there's also this status variable here So we're going to produce uh some filters that allow us to filter on those two different values Um, and in order to do that, we're going to we're going to use this select input Function, so you'll be using this quite a lot. This is quite a common one And it looks like this This thing here that allows you to kind of select different bits and pieces. That's what it looks like So this is obviously very familiar One of the nice things about shiny is that you know uses the language of the web. So um, it's all um Everything works as you'd expect it to um So we're going to get rid of that. We don't want the slider input. That's no use to anybody And we're going to find some select inputs so As I mentioned always the first argument is the name that we're calling it again slightly artificially we actually already have um Defined which is it's here um So it says input year down here. So that means by definition we have to write year up here And then it's the user friendly label. So let's just Do it like that. Um Now the other arguments for select input. Well, let's just pop up the the the help window so you can see uh There's a couple of important ones already the most important one is choices So obviously when you when you're using uh, something like this, you have to tell shiny what The options are and you can list the options um You can just say what they are So you could for example write, um Sorry, I thought I turned my slack off, but maybe there's something else Chattering away it's a bit a bit distracting um Perhaps it's twitter. I don't know. Sorry um So you can just sort of list them out if you want to sometimes it's worth doing this So like if it's like gender or something you could just type them um like this So we got that um But we're not going to do that Because that can be a bit laborious. Uh, if you've got lots of categories or you don't know upfront what they all are So instead we're just gonna and I'll write choices Explosively just so you can see it. We're just going to have the unique values of the data Um, so it's unique values of uh shiny contact data Yeah Which obviously will return Those years 2016 to 2020 basically the other values um So those are all a mandatory argument those three of the other mandatory arguments. So just To kind of illustrate. I'll just run it now and just show you that it's not quite what we want just yet um Because what that does is it gives you a control that only allows you to say one at once And clearly often that's what you want. You want, you know, you don't want you to say lots of things It's not meaningful to say lots of things So if they're selecting like county or something you might want to just limit it to one But we're not doing that So we're just going to set multiple to equals true And the other thing you can do is you can also tell it what you want to be selected first. This is this selected argument um I think it's a good idea to this in this case because often it from memory. I think if you have multiple equals true um You end up it'll it'll just be blank if I'm positive. I don't know why I'm looking up. I'm positive about that So when using multiple equals true, it's usually a good idea to give a default answer Just so the dashboard's not blank when it loads Sometimes you might want a blank dashboard when it loads it depends but often you don't So let's just define the selected argument two and let's just say select equal 2020 Oops. Yeah And then you can see this is the final thing. This is what we want Where is it? Oh, I need to press stop. I think that's there we go Yeah, and there it is and now you can see we can select multiple things And we can delete the ones that are already in there too Cool, so that looks right. It still doesn't work though because we haven't got the we haven't got the other bit working So next bit, um Just another thing to note in passing it's can be a little bit confusing. I think or confuse me when I started You'll notice that in the output there are no commas You just define output is this You sort of define them, you know, they like functions But in the in the ui you'll find commas between things So in this sidebar panel So there's one here that I've already put in without mentioning it and then we're going to put another one here um Just worth just explicitly noting because you can trip over it sometimes and it gives you weird bugs So now we're going to have another select input And we already know the name of this again because this is just like this artificial example. It's status Um, let's give it a nice Label for humans Then we're going to do the same thing again Choices equals unite unique shiny contact data like this Except we obviously do it one year. I might just press return actually because I'm a stickler for the 80 character element. Um So this time we want to just check over in the data. What is it? We're filtering all we're filtering on status So it's just here So we just run that quickly. You'll see what it returns. It just returns all the different types of things that can happen in an appointment Well, I cannot get my twitter to shut up. Whatever I press can I? um Like that Again, we want multiple equals true and Let's select something. Let's select seed Just for instance um Okay, cool. So we've we've done it. I hope you've all kind of followed along with that reasonably well I'll just do a brief recap at the end So if I run it, hopefully it'll work beautifully Yeah, so here we are. We've reconstructed it. Um So these both allow multiple selection Uh, and so does this And you'll see if we give it like an impossible value like this It'll just do nothing There are ways of of of dealing with with that because you don't that's not a good experience for the user really being Being allowed to kind of make this kind of mess and then just having this big blank mess um And there are ways of doing that and I will I will mention that later on Cool, right. So just to recap the main points Uh, we built application from scratch. We've loaded the data right at the top along with the packages um We have uh, oh, I didn't update the title. I was a bit lazy on me um You probably noticed that all of you and changed it sitrap instead um So yeah, basically we pulled out the sidebar panel and we defined two new inputs in it. They're both select inputs Select inputs have three mandatory arguments label. Well our label like name our name label human label And choices you always have to tell what the choices are so it knows what list to show We've chosen to have it as being unique values of this of this variable because otherwise we'd have to type them all in um We've added two new um outputs table and graph In the main panel and they're just on top of each other like this um Oh, that's interesting Someone's just written in the chat the unique and it doesn't seem to be necessary choices equals works to and doesn't produce Stupid values. I suppose that makes sense, doesn't it? Yeah, that's a good point. Yeah. Okay. Well, I've learned something Yeah, let's yeah, I can see why that would work actually because it can hardly give you multiple values of the same thing Kind of that wouldn't make any sense cool um Right, so that's the ui um Well, that's what we did. I suppose the ui isn't it um Yeah, and I gave you this as I say I gave you this it's just it's very I'm sure many of you can read it if not all of you um It's just very simple code that just draws a table and draws a graph unused argument multiple equals true Oh, you've probably got a bracket in the wrong place. I would think to be honest. That's the usual That's the usual thing I suspect have you have you missed out the bracket after unique until the multiples crept into the unique Oh looks like a typo. There you go So this is quite good at clubbing. This is a big group. This is going quite well It's a shame you can't all are kind of talking on me already, but I do think that would be chaotic. So But we're going quite well um Right, is everyone happy with that does that make sense? We've all built a shiny application from scratch So you're all doing pretty well Cool, right. I'm just gonna crack on do Anytime you want me to throw the brakes on do just shout up in the chat. I'm watching it fairly closely So I'll be right. We're not really In a rush to get through the material so we can it's fine to kind of pause a bit And dwell on any issues that come up for people um Sorry, I'm just trying to find my window um Oh fire wall asset, yeah Yeah Oh computers they're fun aren't they um Right back to the slides. Where are the slides? You want to find the slides? I can't find them. They're Here Got it Oh, they were here the whole time Okay, let's not have two copies of the slides over that seem more confusing Right, so we've done this so again, this is to be honest This workshop code is more for live because I would have it all behind me But there's absolutely no point doing that because you won't be able to see it um Right that's kind of basic shiny. So you're all certified as like basic shiny developers now So now I want to teach you like how to layer things on and and do more complicated things in a better and more efficient way So the first thing Is reactive expressions so reactive expressions are really really really important It's probably the it is probably the second thing you want to learn and that's why it's the second thing that i'm showing to you um, so A reactive expression is just like a reactive output like a graph Except it's not a graph. It's a thing. It's like a like a data frame or a piece of text Or it's like something that can that has some useful status in ours very often a data frame But it could be anything could be like a list And the point of having reactive expressions is basically allows you to have all of the the code All of the server code that does all the data fetching and clean code and all this kind of thing For several different outputs in the same place So just go back to the app that we we've been building um This is sort of there's a big problem with it and it doesn't matter because it's such a trivial app but um You'll see the the big problem with this is that we've done the same thing twice So we've done this here and we've done this here and that is just that's how shiny works If you want to do something in an output You've got to do it in the output So i'm sort of repeating this code now obviously this code is very simple and and fast-running But of course in a real world situation you can have code that's either very complicated and difficult to maintain you don't want to be copying it all over the place Or equally it could take a long time to run So i've got server code that can take you know 15 20 seconds if it's hitting a database You clearly don't want that on four outputs. That's that's grotesquely wasted your user's time um And that's one of that's one of I think one of the fun things about shiny is that it really makes you question these things because when you write kind of slow code for yourself I don't I just tend to write so I go and not think about it too much But I just go make a cup of tea and come back and it's done But you can't do that with shiny because you've got users You've got people who are using this stuff and if they if they think the application is too slow, they will not use it So you you're in a bit of a game with them really trying to make sure that you're doing everything at the right time anyway So they allow you to to create and maintain the code in one place Which is helps you to kind of have you know Code that's kind of neat and all in the right place needs to maintain But also they cash their results So once they've run once they don't repeatedly run again for every single output They just keep the they keep hold of it and they will give it to several different outputs Um, so yeah, so if you're using a lot of bandwidth or using lots of compute Um, and that's the other thing that's interesting about shiny, of course is why this very often you're running on a server So not only are your applications wasting your users time. They're actually wasting the server's users So you could actually be giving other people on the same server a bad experience um So you it is a it is a new way of thinking I think for some data scientists So just to illustrate this principle. I'm discussing graphically This is kind of if you write shiny in a naive way, which is this is how I started writing shiny This is what you end up with so you might have a couple of inputs Say, I don't know like date or clinical area or something like that Um, and you might have a couple of outputs Um, and every time one of these updates both outputs will rerun Yeah, so this output has got all the code to make whatever it is inside it all the data and everything Ditto this so if they're based on the same data object, they're duplicating work And the same with this one when this changes these will both rerun as well So that's not what you want. That's backed except in rare circumstances. That's not a good idea What you'd rather have is something like this and so what you do is you just basically put this thing in the way this reactive Expression that goes in the way And that forms a dependency and again, this is all done automatically as I'll show you so that forms a dependency So whenever input one changes the reactive object will update and whatever input two changes the reactive object will update But it doesn't update each time an output wants to rerun. So if you imagine this is the date You change the date The reactive object thinks for itself. Oh, yes, I need to change because the date's changed So let's rerun and then it will feed that on to all three outputs So these outputs will take a dependency on the reactive object So the input tells us the reactive object to update Then the reactive object updates itself and then feeds the same data without rerunning to three outputs So as you can see Very clearly, it's much more efficient. Obviously not all shiny applications do this But many do many have this big hulking data there that is passed around different bits of the application And there's absolutely no point whatsoever Continuously recreating it So that's why we're doing this All right, so just pause briefly just to make sure everyone understands the the principle because now we're going to do it That that's that's what we do and why we're doing it. I'm going to show you the code in a moment Cool. Now everyone seems happy. Right. Okay, so This is again, this is sit rec second So in order to um completely this exercise we're going to um Sorry, I've got so many uh, so many things in my uh Yes, here it is zero second. So as I mentioned the answer is always in here um Inside a folder called sit rep second and the sort of the the the bits of fragments of code that you need to complete it Are in sit rep second r So I'll just open that now I'm not going to show you a demo on this one because it looks exactly the same as the last thing We did there's no difference whatsoever We're just making it run More efficiently more correctly um And so this is what you need basically so you're going to need the first application that works So you can either use the one that you just made yourself or if you didn't because you got distracted or because it didn't work Or whatever then just go in the sit rep first folder and just find it and use that one because that's the correct answer It might look slightly different to this one. I can't remember what I did last time but it looks something like that Um And then we're going to add this to it um So this is all this time. We're not touching the ui the ui is all the same. We're just going to serve a code this time so What we're going to do is we're going to define a reactive expression And the way we do that is very simple. We just give it a name any name you like as long as obviously it's followed in r And then we just use this reactive function um And Yes, you'll see so the reactive function obviously has got oh, yeah, that was I didn't know that um Has got a normal bracket for a function, but there's also these little curly braces just to go around everything that you do Because you might have like multiple. This is a very simple example. You might have a very long complicated reactive expression um And all we're going to do is we're going to take the data and we're going to do these common exercises As they already as they're done. So you notice in the first application. It's done twice So this filter and group Oh and even summarise these first three lines even I've done more than once on this. So these these three lines here are repeated so we're going to um We're going to do that once in the reactive expression um And it's the other that is the same data operations um And then once we've done that we're going to then use the reactive expression throughout the application And the way we do that is it's just like this. We just use the name And that will then return whatever's in here. So whatever this function here returns Will appear there Now I'm just going to pause momentarily just I'm going to hammer this point home because it does create annoying bugs as I found when I was learning shiny You'll notice this has got round brackets around it um And this is important to understand now, but it's even more important later on especially when you're using modules This distinction becomes very important So Without brackets. Let's just take the brackets out for a minute This is not a data frame This is an expression. This is like a way of doing things. So the another gi always give is This thing here is like a is like a recipe. It's like a recipe for like apple pie or whatever. Yeah, so it's not a pie You can't eat it It tells you how And so it's no good. You can't you can't pipe this into the spread argument. It doesn't make any sense Because it's not a data frame But when you put the brackets in it is so the brackets is like saying to our I know you've got a recipe for apple pies Can you please make an apple pie and whatever comes out of the recipe? You know give that to me. Give me the pie. So this is the pie with the brackets. It's the pie Now obviously like I'm laboring this slightly. It's just when you start using modules You are going to be passing Both reactive expressions and the contents of reactive expressions around And if you haven't taken the time to absorb this concept, you are going to get in a horrible mess as I learned through a bitter experience So and also just remember to put the brackets in just as a simple debugging exercise. Um I do think I'm pretty sure you get the classic. Um What is it objects of type closure cannot be subset? I'm pretty sure you get that classic error So if you see that in the shared application, that's the first thing to check. Have you got brackets for your right of expressions? So yes Not to bang on too much return data with no brackets is an expression. It's a it's a thing It's a recipe with the brackets. It's a it's a thing that you can have like a data frame or a pie Um, and that's how you use it. So you just pop it anywhere you want that thing and it will um And again, it's all as you'll see it's all done automatically So this is automatically forming a dependency on on the reactive function and so is this But the reactive function is clever It won't just run over and over again It will just run once when the input updates and then render tt will ask what's in it And it will say certainly there you go And then render plot will also ask what's in it and it will give it the same object It won't do anything else. It will just sit holding that bit of data until it's asked Right, so that's that so I think I've banged on about that enough now um So I'm not saying anything in the chat so do chat up if you're confused or you want me to reiterate anything But for now, we're just going to do it. So we're going to take the application We've already got that works and we're just kind of kind of neat nail it This doesn't make it do anything else. It just makes it more correct um I wonder if I might have to pop this out actually that might be helpful might as well just pop this out put it over here And then maybe pop this here just so you can see What I'm doing this this column is not terribly helpful. So I just slide out of the way So The retro expression is defined as you might expect within the server bit because it's doing a thing So we're just going to define it over here like this Pop it in doesn't matter where I'm going where it goes All right um And this filter group by summarise this is the this is the duplicative This is duplicative stuff from earlier So it's this So it's going to get rid of that I'm going to put it here So now this bit does the same thing that all that gobbins down there did So now, uh, we're going to rewrite it. So we don't want We want what's in this reactive expression now in this table. That's what we want So as I mentioned before it's a reactive expression But we want the pie. We don't want the recipe So we're just going to pop that in there like that and we're going to put the brackets around So that will say whatever's going on go and fetch that and bring it back and whatever that is I want you to pop it in there like that And then the exact same thing of course up below Um like this Uh, where does it go? Yes here? Is that right? Yes Oh, no, I need to take the top line out as well All right, first of all, it's got it. Oh, is that common as well? No, there is no reason probably just because um Because I didn't notice um Both on group down there. Yeah, no, you're quite right. That's a good point. Yeah, let's do that I suspect the real reason is because I added it later and then forgot Um, but obviously let's get it right And I've confusingly got a base our pipe and the other pipe middle up now is just a bit annoying, but You have to forgive me. I'm sort of between I'm currently adopting the base our pipe so pops up with the old pipe Beautiful. So that's all you do. You just take your data you pop it in your active expression And then you use the brackets to return it wherever you want it. So hopefully if I press run I haven't just broken the whole thing Let's find out Yep So as I say, it wasn't doing it. It doesn't look completely different because it's not supposed to it's just doing what it was doing before in a better way So that's cool. So we haven't broken it Um I think we're doing a lifetime. So yeah, we've got another 20 minutes on this first session um And I might just pause maybe I'll just pause for like two minutes in between the sessions just to give you a brain's chance to Do something other than listen to me um Oh, what makes the base our pipe displays the arrowhead excellent question Uh, you need to download A font that does that Um, so the one I'm using I think is called Fira f i r f i r a um I'm sure there's a blog post about it somewhere if you google it Didn't find shiny contact data Oh, I suspect Yeah, sorry. I don't know where you we need I didn't probably specify this we need this low data at the top You probably just haven't copied that across to the new application So it's a pair all the way at the top there So it's all the same gubbins that we had at the top of the previous app. Otherwise it won't work But yeah, so have a look it's called Fira or something that does a cool um Getting off the track, but it does a nice not equals to as well. So I do deeply love it. It's pretty cool um right, okay, so I'll just go to the slides um Yep, and again, this is all stuff I'd have in the background Can you put that in the chat for the pipe display in the? Uh Yeah, I mean it's just the it's just the common garden um It's just the common garden symbols like this Uh But they just automatically um Change to um I think they're called code ligatures. That's what they're called You hear it is front. This is just a random blog post that I just found but I'll describe it to you This is part of the fun of workshops Isn't I always think that it's fun to see other people's environments because they're often doing things that you're not Doing that you want to have a go with I often think that um Right. Okay. Everyone seems happy so that you've you've completed successfully all the exercises in the first section So we've got one more section to do after a very brief break. So now I'm just going to do some talking um so um Right debugging so I I will be talking a lot about debugging from now on um Because Debugging I mean much as I love shiny. It's quite hard to debug. I'm sure it's nobody's fault, but it is um Because the error message is well, there's two reasons why it's difficult to debug The worst one is that the error message is just not very good and as I say, I'm sure that's no one's fault Um, but it can be really hard to understand when you've got an error message what It's referring to like what output's broken or and the other thing it does as I mentioned earlier Is that sometimes well quite often in fact It will just not work, but it doesn't give you an error message. You just does nothing And when you're just looking at nothing it can be sometimes very hard to understand It could be all the way from something trivial like you slightly misspelled an output to something Incredibly long and complicated and difficult with the data and it's it's hard to know where to target really So because shiny it's so difficult to debug I recommend a sort of highly defensive programming approach particularly when you're learning I mean, I still I mean, I've been writing for 10 years and I still use a highly defensive strategy um So the first thing is start simple use the wizard as I mentioned always use the wizard um, and I mean I suppose it goes without saying what I'm going to say anyway I only change one thing at once Don't write loads and loads and loads of shiny code and then press run. That's never a good idea ever No, how good do you think you are? Just don't do it um The other thing to say is and I see this very often on stuck overflow is people write code for the first time Like say draw a graph or whatever in shiny So they'll sit there in a shiny code file and they'll type a graph blah blah blah blah Then it doesn't work That's really not a good idea because it's very hard Because because shiny's Reactive it's like a sealed box. You kind of start it running and you can't look it's not like working interactively in r Where you can just look at the you know, look at all the data objects and mess around with them and test if they're equal You can't do any of that. It's just a totally sealed box. It's just running So debugging outputs in shiny is never ever a good idea. Never do that again no matter how good you think you are just don't um Just write it anywhere um You know like an r markdown file and r script or whatever and then port it across I mean really and truly the the the right way of writing shiny applications is You have thoroughly tested and packaged code in another totally separate package than functions that you call um But that's kind of slightly more down the road in times of trying to build very robust applications I mean, that's you know, that's the the ultimate way of doing it But certainly don't write stuff in don't debug outputs in shiny. It's just frustrating um There are ways of debugging shiny um that are not obvious So I've I think I've showed lots of people this over the years people who can write pretty good shiny don't know this um So for example, you can use cats So let me just show you how incredibly useful this is as I say I know people who can write shiny who didn't know this which I think is absolutely testament to how good they are because I Couldn't do this. So let's imagine we've got an application And it's not working something's going wrong. It's drawing the wrong graph or it's blank or just just being annoying And we're not really sure why um Oh, let's not have this application. That's oh, where's it gone? Where's the one the reactive one gone? Must be a different screen Uh, isn't this one? Is this the reactive one? Yes, here it is Yeah, so imagine we've written this application and it's not working properly. It's doing something annoying that we don't understand Quite often the problem can be in the data Or in the inputs that might there's something inside either the inputs or all the data that you don't know is there It's either blank or it's garbled or there's something wrong. And as I mentioned, it's you can't Just look easily inside shiny. So what you do is Imagine it's the the the table that's not working properly. All you need to do is just write cat And then you can just write anything you want to see just write it in there So for example, I might want to see what the data looks like. Oh, no, don't sorry. Don't do that. Don't write cat return data That's terrible idea cat str return data Just in case anyone hasn't heard of the str function str function basically Uh, it just gives you a little Sort of summary of the structure and object. It's str stands for structure. So for example Just illustrate if I write str empty cars It comes up with a nice thing like that that just shows you what all the variables are and what they all on that kind of thing so clearly if we return if we call this on A data frame that we're having problems with and we're not sure, you know, why because obviously it's here in a database Or it's based on input or whatever is Um, that will help us. So if I now press run You'll see It shows you So we can now see so the classic problem is oh my shiny application doesn't work. Why not you type? Ask me I've returned data Uh in here and then it will say tibble 57 by zero And it'd be a blank day for him And that's very very very common because you've set one of your inputs wrong You put not equals and you mean equals or just you know, the database is broken or you know something Trivial like that that shiny will not easily tell you it will not give you the answer straight away because You know shiny basically doesn't know what's wrong with your code So that's that and you can also use it on inputs as well Sometimes you're not you're confused about what the what? If the input's based on something else, you know, if it's complex Sometimes you're not even really sure what's going into the application amount of what's coming out So you can use you can do the same thing there um So that's quite useful cat Um, you can use breakpoints and browser. I'm not going to go into what they are But you can certainly if you haven't heard of them, you can certainly do a bit of googling That's just common garden bog standard are Uh debugging I'm just mentioning that that you can use it So for example, if you've got a shiny application and it always fails at the same point Just put a break point just before that point if you can figure it out where that is And then it will do the normal thing that break point It will then will just stop and you can just go in and have a look around It still can be difficult because shiny applications can run And this is something I mentioned at the beginning about doing things automatically shiny applications um run when they want to run like the the individual components um They do what they want So sometimes they can run in a funny order that you're not aware of something else is happening before this and so that can be confusing um, so But yes, certainly that's um That can be a problem. Sorry. I'm just writing um just writing the str thing in the chat Okay, so that's another way another way is Uh using what's called the real as well. I don't know. It's I guess it's called a reactive log react log for short This is pretty cool. It can be hard to use But it's pretty cool So again, obviously you've got all the sizes on get out and stuff and whatever So don't you know, don't worry about if you're not kind of making copious notes Just run this. So I'll just show you again So go into your application. That's the wrong window Go into your application and just run on the console shiny dot reality equals true That's the first thing you need to do now run your application Obviously this application works, but in this imaginary university imagine it doesn't work And there's a particular point at which it doesn't work. So let's imagine That when I I had a few things I go, oh, that's okay. And then when I run our dna Let's just imagine the whole thing just explodes and doesn't work So you need to Do whatever's breaking the application. That's that's the key thing here um and then You need to press control f3 Firefox is only this side of an open pop-up window. No, please do Uh show this one And when you press control f3 After having run options dot react log equals true This will happen. It's taking a moment to load for some reason. I wonder if the r session is happy in the background. Let's check Oh, yeah, sorry. No, there's uh, yeah the first time you run it you'll get a little Thing that says you need to install a package to make it work I might not I've just gone up to r version 4.2. So my packages are not loaded Yeah, here it is So let me just check it from the top for you So what this does is Yeah, so I just click this button right at the far left just to take us to the because it will start at the end We want to start at the beginning What it does is is it shows you all the Bits of your application how they all interact with each other. So you see there's a key down here. So green is ready to go oranges i'm figuring something out um And these these two sorts of gray Are shiny is not what sure what's in those So like a perfect one if shambigation is finished running and come to rest everything will be green But every time you click a button Bits of it will become gray because they're like, oh, well, I don't know what's in that graph now because you just change the date And then it will all the gray will populate through and then it will all go green in it. So let me just show you can just step through it So um, so this is the first thing. This is it basically loading um Some of these are a bit weird. I mean, that's the thing is it you know, it's So for example, you've got all this client data pixel ratio. You obviously just ignore that Um, and this thing here just ignore that. I'm sure that's very important for somebody um But it's not important to it's never been important to me Um, so just look at the things that you know what they are like output. You know output graph and all this kind of thing Then we're just going to step through So you can see the first thing that shiny does when it loads is like, well, I don't know what's in I don't know Oh, no, sorry. The first thing it does is this is I don't know what's in this one. So it's gray Then it says, well, let's find out so it goes orange And then It says, well, I can't find out what's in me until I know what's in this and I don't want this in this either So then again, again, it says, okay. Well, let's work out what this is And then it goes to the input year and it says what what's your value and it even tells you on here What the value is which I think is genius So the input year is telling me that it's 2020 And then it will go to the green one It will say input status is telling me that we're looking at just the scene appointments And then you'll see now Return data is happy now return data is like, oh, yep. No worries. Yep. I know what I am now And then output table says, oh, well, that's cool. Well, I can work myself out because I know what you are now so now it's gone orange and I don't know what that is quite honestly that bit But I just say you don't have to look at all of it and then it goes green So this this one's happy Then the same thing again now the graphs like well, I don't know what's in me either and it will go here And it will go to return data I guess all this weird stuff first. Let's just ignore all that And you'll see you can even see the caching see So straight away it goes. Yeah. No, don't worry. I'm green. I know I am And then I guess fade it fed through to the graph And it's all green So we'll finish green and That's really useful Partly just so you can see what's connected to what if you get confused, but also when you're doing more advanced stuff You are sometimes Sort of telling our don't do this first don't do this until you've done this There are ways as I mentioned about kind of threading it together Um And that can be tricky to debug without this kind of thing. So You probably won't use it. I wouldn't think if your early days were in shiny, but As you get more advanced, I would just try to remember it's there Um All right, I've lost the slides again now. Why do I keep putting the slides hopeless? um Okay You'd like an artificial intelligence program that just knows What I want to look at and shows me All right, sorry. Let's just skip through again. Blah blah blah blah blah Debugging right. That's it for debugging. Is this the packaging? Yes, it is It will prompt me. I mean, it's dead easy if you do if you do why I did naively and forget you haven't installed it It will just say is it okay to install this and you say yes, and it will just do it But yes, that is the package Right, that's debugging Um Okay, there is extra material depending on how long this course is or how fast we're going sometimes I do The extra material that I don't Well, I feel sure we haven't got time to do it today actually. Um But it's here for Those who want it after today Um, so oh no, no, I'll tell you what no, I'll I'll just go through this verbally. No, sorry I will go through this verbally, but we won't we won't we won't code it. We'll just look at it because this is really really Um useful I think for a lot of people So just this is just a quick, um summary um You need, um This is all about non-stun evaluation So I'm sure some of you would be very very familiar with that. I don't know if you will all be familiar with that but it's the way that that sort of variable names can get passed through functions in r um and There's loads of stuff written online about it. There's loads of different approaches to it. There's it was bang bang for a long time the Exclamation mark exclamation mark thing And there's a new way of doing it now And I can't remember what that new way is called on a curly curly. That's the new way of doing it. It's called curly curly um So there's a whole I'm just saying there's a whole thing to this that I'm not going to really talk about I'm just going to talk about the specific example of I've written a shiny application And I want to pass a variable name to a function from an input. How do I do that? Because people often Stumble on this and I don't think you need to understand forwards and backwards non-time evaluation in order to do this You just have to memorize what I'm telling you So this is an example. So this is this is when um, this is when non-time evaluation is not working Um, so you can't do this you can't pass in bare variable names to functions in this way Um, because it doesn't it doesn't know what what this what this is this gender So it doesn't work after the box But what you can do is you can use curly curly like this and then if you by using curly curly r knows to pass it through Um And then this gender this this bare variable name does get passed in here and then it will work as I say I'm just I'm not this is not supposed to be like a full Session on this. I'm just recapping. Um, this is the the nuts and bolts of non-time evaluation. It's passing variable names um So that's how you do it in in the common garden programmatic world Which is what most people are in so most examples you see we'll do this But the problem that we've got shy devices. We're not doing that. That's why it's so confusing um Because we're passing strings. We can't pass bare variable names because for example This the uh select import. It's just not return bare variable names. It returns strings And it will that will not work. So that's no good. Um So what we do instead is we do We have a different curly curly So this is the curly curly. We're bare variable names So some of you might be familiar with uh, this is our curly curly as Either shiny developers or people who are passing strings for whatever reason they're passing strings. It's dot data square bracket square bracket And the the the variable name in this case by by equals gender So our writing dot data's square bracket square bracket That says pass this string through and then filter based on that as a as a name um Essentially what it's doing is it's just this is a sort of this is like I think it's called a pronoun It's saying take this data frame and then just apply double square brackets to import a string in Which as you'll all be familiar with that is how you return a column um But it's just this is like a special data pronoun that will work with whatever the value of the data is as it goes through so it's kind of it's like a special instance of data um And that's it really I mean it I think truly understand it. It's quite complicated And I don't as you can probably tell fully understand it myself all of it. Um But I can certainly pass variable names and shiny applications and that's how you do it It's dot data double square brackets the name of the thing dot Um, and if you're interested in all this stuff and understand information all this kind of thing Then I would encourage you to really curly curly. That's the best thing to read If you google curly curly r There's a great vignette on tidy person or one kind of thing Okay. Yes. So and as I mentioned, this is the kind of extra homework that I leave sometimes um So just have a look at that if you want to uh In you know tomorrow or whenever you get the chance. Um There's one or two look like so you can do that Cool, right that session one finishes exactly in 90 minutes, which is promising um I think I'm just going to just Pause for sort of two minutes just to give everyone a bit of a kind of I'm going to just going to stand up and stretch my legs And then we'll be straight back into it with session two which obviously has then got more kind of uh Advanced shiny type stuff and is everyone happy because everyone want to pop anything in the chat Before we just go on a very brief hiatus No, okay, cool. Um, just for the avoidance of ambiguity and I've obviously no idea what time it is where you are uh When the time has got a 35 at the end of it wherever you are Let's meet back end. So that's four minutes. So it's half past five where I am I've no idea what time it is where you are But at 35 past whatever an hour it is in your country That's when we'll start back Cool, right. Thanks everyone. Right. So this is session two so I mean, you certainly got the basics. So that's good, but we're going to keep going Um Oh can't skip the side. Oh, there it is Um, yes, I'm not going to recap because you did it two seconds ago. Sometimes I run this over multiple days So I need a recap Um, so we're going to build another whole application again. Uh, this time looking at um Accident emergency data And we're going to be learning mainly stuff to do with the UI this time It was sort of server focused last time um Just going to show you this is more kind of like neatening up and making things a bit more streamlined and stuff But this stuff is really really really important um to If you don't do this stuff your application could be very confusing. Um, so, um It's it's it's worth knowing all this stuff um So, yes, I'm not going to recap because I just did it right the first thing we're going to do Uh is we're going to learn how to uh have more than one output on the same page um This is obviously pretty important um because You're almost always going to want to have more than one I mean you can just stack as we did before you can just stack the outputs on top of each other forever If you want and have a really really really long shine application But that is not good user interface design. Um, so I would not recommend that you do that um Instead we're going to build what's called a tab set panel. Um So let's just have a look at that Um, I've honestly got so many windows open and I've got no idea what's going on now um No, I'm gonna let me just Probably this no. Oh, that's the pop tower one, isn't it? Okay, so I want This one, okay So we're going to change with different a and e um, sorry different a different application now And the application is called a and e accented emergency So we're going to start with the a and e uh first So again the answer is in here. Um, so let's have a quick look at the answer first Um So we're basically looking to build our application looks like this Yes, this is a deliberate mistake in here. Um, which we're going to look at later So you'll see when it loads There's a big error message that says frasting variables This is not a very good experience for your user What are in fact wants you to do is select something over here and once you do it's happy um But loading into that screen is not a good idea and I will we're going to deal with uh, how to avoid that In in this session Um So yes, what does it do this application? So basically it allows you to select a date range over on the left It allows you to select an NHS trust an organization Um with an a and e department It draws some graphs I mean, it's very stupid. Well, this is not a realistic example at all It draws some graphs of the um the ascendances To any in those places And there's a little map thing as well So we're going to draw some maps just to kind of just for fun or anything just because they look cool Drawing maps can be a bit fiddly and are But we're not going to worry about that today. I'm just going to kind of just show you how to kind of load in I'll let you worry about how to how to draw your own maps with your own data When you get back to uh to your your your daily work So We're going to open the a and e code first File here this thing a and e code underscore first dot r we're going to open this And that will show us um Everything we need to uh make it work Um, so again, there's loads and there's loads of server code in here So just we're just I mean, I'm going to show you in a minute But just copy that in because obviously there's no time at all to go into all the Where's I mean, it's not complicated. Um, but yeah, just just just trust me That this data produces a reactive data object here And then it draws a map of it and then it draws a graph of it And just don't worry too much more about it. Um What we're more interested in is the is the the UI So we're going to use sidebar layout here We're going to um put some dates in as in the original application We're going to have a select import which will allow you to select the trust Um And then we're going to use the the main panel function to layout the the tabs I'll just lay on this on the slide actually Uh, I think it's on the next one. Is it or is it on the previous? Oh, yes. No here. It's just sorry. It was on the previous slide um so What we're doing basically is we're building an interface that allows you and again, this is just the language of the web So it's very familiar to everyone It allows you to select which input which output you want and you can have lots of these tabs as well So you can have you know graphs and tables and blah blah blah all the way along Um, so we're going to write code that does that it's pretty simple It goes in this case in your main panel code, you know in a in a in a side panel layout It will go in there and all you do is you just have there's two functions One of this tab set panel tab set panel, uh, we'll draw the Draw the whole tab set panel layout the whole thing and then you put individual tabs inside it um with each With what each of the tabs is so this first tab here will appear on the left This label will be whatever the user sees it as so in this case it would be graph here Uh, and then uh, you can write anything you like in it. You can have multiple again You can have multiple outputs in here if you want It's kind of more natural to have really one output on a on a tab, but kind of depends maybe a few small ones um And then the same thing again, you just keep putting all the tab panels you want into this as the number two So in our case it would be map And again, you just put whatever output function you want. Um, and it lays it all like that So relatively simple to use um So that's what we're going to do. So I'm going to pop this code out again. I think that seems to work pretty well um So stick that over there um And we're going to start from scratch Uh, because we've been doing uh, uh, we've been doing a sitrep application up till up till now Now we're doing something else So let's just um You know, that's right Let's just put this over on the left. I think you should be able to see all of this at once pretty much like that Right, so we're gonna do the same thing. So let's all do this together same drill File new file Uh, where is it shiny? Where? I'll be here and again put it where you like And I'll call this one a and e And this is obviously the template you're now very familiar with So we'll get rid of all the gobbins at the top just because it gets in the way Um I'll update the title this time because I forgot last time a e Right so now we want um A tab set panel with all the outputs in and we want a sidebar panel with the date In and to select the trust in So again, if you feel happy and you want to just have a quick, um Quick go like yourself then feel free to just get stuck in Uh, but if I was just wondering if I could pop this out, but I can't really get too crowded um If not, I'll just be I'll just be doing it and you can just kind of follow along and see what I'm doing um So let's just get rid of all this stuff first because it's just distracted me. So let's get rid of that. Let's get rid of that So we work on the UI first, I think that's logical. Um, oh no, of course, no, we've already got the server. Let's put the server in first So again, it's it's a it's a bit kind of um Unnatural this because I'm giving you the whole server code And obviously in real life, you'd write your own server code Oh, no, we don't need to copy that top line there, do we? like that So paste that in there like that um And again, I forgot to mention this last time we need to make sure we've loaded all the bits and pieces at the top So we're going to load The packages that make it work And the data right right at the very top Cool. So we've got the server we loaded the packages. We loaded the data So all we really need to do now is usually just stitch the interface together and it will work So let's start with the inputs So the inputs are it's these functions date range input And select input. We've already seen select input Date range input is very helpful very handy function Uh, and it just produces these little boxes And you can just pop them up and you know, I'm sure you all see these on the web. You can just Kind of click the year and you know, click whatever you want click around and put put the thing in So that's what they do So Where are we here? So we're going to use one of those because we want the users to be able to decide the year that they're interested in and Again, not forgetting the first argument is always what shiny is going to call it Now again, unfortunately, this is an artificial example. So you actually have to do what I did Um, so if we look down in the server file, you can see we've already got a data input defined down here And it's called date So you'll have to call yours date too. Uh, and then a user friendly one Uh, maybe date range because it's going to be two dates Oops date range And you need, uh Two more arguments And I forget the names of the arguments. Honestly, let's press tab and find out. Oh, yes start Um, oh no, actually, no, they're not. Um Oh, yeah, no, they're not mandatory arguments But if you don't put anything in them the start date and the end date are the same Which is never what you want or very rarely. So we will put a start date in Um, I've hopefully actually included a start date over here. I'm nice. So let's just copy that April the um April 2016 And we're going to put an end date as well I mean, you could arguably just leave it to be today's date But that's maybe just a bit confusing for your user because they might think this day today when there isn't Okay, so that's the date range input that will produce uh a display which when Start will start on the 1st of April 2016 and finish on the 1st of march 2019, uh, and obviously will allow you to select values Among it's there are some other arguments you can like select the max value and various things like that But we won't worry about that today Um, so we've done that and then we're going to have another of these, uh, select inputs Um that we've already looked at. I think this is probably by far the most common Uh shiny input there is We're going to give it a name again. It's already got a name unfortunately So we have to just use whatever I've defined it as it's here trust Input dollar sign trust so are we right trust up here? Then we might write a select trust here And then we've got the choices argument um And what I've learned something so I'm not going to write unique anymore. I'm just going to do it The clever way, um So in order to do that we need to just have a look at the data Um, so I'm just going to let's just pop this window bigger for a minute Let's clear out the old data because it just confused me having it in there And load the new data There it is. Right. So we can just have a quick look. Um So as you can see there is a date That's called period Um, there is a name that is the name of the organization that is the trust thing that we're interested There's an org code as well But it's just like a weird like three letter code thing that we use for administrative purposes So we're not really interested in that um So we just want choices equals a Attendances dollar sign, uh, what did we say it was again? There you go And again, we want to set multiple equals true And when we do just to reiterate this point Because it's going to be relevant later on That's funny wasn't it? um Oh, no, yeah, we haven't defined the outputs yet. No, I'll come back to that. Sorry. I'll come back Yes, yeah Okay, so I'm assuming you're okay. I do do shout out if you're not That's the inputs defined. We've got a date range input. We've got a select input So now we're going to do the thing that we're trying to do really the focus which is the um The tab set panel So it's down here. So this is this is A summary of what a tab set panel will look like like an example prototype So let's just copy the prototype over to here um And then let's give them User readable names. So let's make this Let's have graph first Well, let's see the functions in one at a time actually that's probably better practices, isn't it? um Don't really need to help again anymore so the graph And then we want to obviously on the graph we want to have what the graph is And the graph is called output dollar sign graph. So again, you're going to have to use my names So we want graph output. No No plus output, of course it's sorry plus output graph like that And similarly We're going to have another one here. This is called trust map Um, so let's just pop that in there Give this a nice label like that And just note this I've written a few books like this. There's a separate function for lethal outputs You can't it kind of looks like a graph. So you just think oh, it's a graph. It's not a graph If you write plus output there, I hit them again. I don't think it even gives you an error I think just doesn't do anything and it's very confusing um, so don't don't forget any kind of special output Like leaf that there's loads of there's loads of different outputs you can have in shiny They all have different functions They all have different output functions Um, so just try and remember that otherwise you'll write weird books and confuse yourself Um, and again this label obviously is taken down here Um, I think that's it the only thing just to mention that I haven't talked about because we didn't really look at the server server bit Is just to explain what this it what this date input's doing. So it's called date as I mentioned um, yes twitter talking about the background um It basically it returns a vector with two values. So it returns so input date will hold Date from date two. So as you can see we're just indexing it by one two So it's very easy to use. So it's just one object and you well, I suppose, you know, yeah It's it's a it's a collection of two objects And you square brackets one for the beginning and square brackets two for the end and that's it simple as that um As opposed to there's just a normal date thing that's not a date range Which obviously it's just there's no square brackets. It's just using the date So that's it. I think that'll work Let's see If it doesn't it's all good practice debugging Right, and again, it's got the deliberate error message in it. We're going to fix that in a minute But hopefully when we click around a bit So there it is And hopefully here too is the map There we go marvelous. So you built another application and you've used a tab set panel to have multiple bits Um, so that's sort of the kind of uh tool in your toolbox um Right, so there's nothing in coming up in the chat. I'm just going to push on um No, I said all this there's again, this would be behind me in a real workshop um Right now we're going to do some we're going to do some more tricks with the ui um So the first thing we're going to do is we're going to do what's called conditional ui So, oh no except the slides from the wrong order. So we're not is it no That's not great. Is it no we're going to dynamic ui first So dynamic ui is very useful if you have a large number of inputs But you only want some of those inputs at particular times So the example I always give is I built a massive shiny application that looks at all of our patient experience data across all of our teams And you could in theory have a shiny application where there's just a team selection on the left And it's just got every single team we've had in the entire trust for the whole 10 years of data That would have like 400 options in it. That's not Good user interface design at all So we don't do that In fact, what the application does is it looks at what other clinical areas you've selected and what the date range is because they sometimes disappear reappear these teams And it only shows you those um So that's an example of what we call dynamic ui and this relates to the thing I mentioned at the beginning And this is which is why I mentioned it Shiny you'll recall it loads The whole ui first that's the first thing it does when you press the button It loads the ui and then it never goes back to that code file ever again. You can't touch it And because of that you have to wire up if you want the if you want the ui to change you have to tell shiny You have to tell it what to do And it's not difficult. It's just important to know that that is essential otherwise it will not work um So This is how you do it That's I wonder if I can pop this over on the on the side It's just maybe just come out a bit. No, I don't really want to come in and go to the left really. No, how do I do that? Stupid thing. Yeah, sorry. That's probably not the best uh view um So in order to do that, um There's there are two again. Obviously shiny functions always come in pairs as well as the ui and a server function so The the ui function is called ui output And remembering that it's loaded first what that says it what that says to shiny is There's something in here, but I can't tell you what it is yet because I haven't run the server file So just put put please put a blank space here And then once the server file runs you will know what's in there you can put it in there And that's obviously the way that's the method of making it dynamic because now the server can update it So you're selling the server you feed your operations back to that piece of ui So that's that that's the trick to make it dynamic And the the companion function to ui output is render ui And when you use render ui You again obviously as always use output dollar sign. So the output dollar sign is this thing here as you can see here date range ui And then inside render ui function is very easy to use. It is just absolutely common garden plain ui code There's nothing special about it at all except that you can do Dynamic type stuff. You can have reactive values in there I haven't done that because I'm a bit cautious about putting loads and loads and loads of code in and confusing everybody But I'm just trying to explain the kind of the layout to you really This can do anything you like it can have reactive values It can have seven reactive values It can hit databases it can do anything it can do all the stuff that you cannot do in a ui But we're not going to write loads and loads and loads complicated code today because there's really no point um Note well that What comes out of this the date will be referenced elsewhere in the server as input dollar sign date It uses this identify here not this one This identifier is used to put it on the screen This identifier is used to return the value I'm just telling you that because that can also be a bit confusing and it tripped me up a few times Because of that I've come up with a system where whenever I have a ui I always write ui in capital letters at the end Because it stops me from getting confused because if I had something in my thing that said date range I would start get confused and start thinking. Oh, that's what it is It's date range and I write input dollar sign date range And chinese wouldn't have a clue what i'm talking about because that's an output not an input um So that's just a little piece of advice you can if you wish you can copy me and just put some sort of thing here Because you can write a lot of this, you know, if you write a big application you can have like 20 of these easily So it can get very very confusing what that what everything is So I would recommend that you have some sort of clever boilerplate way of telling them apart Um But other than that, that's it really. Um, so let's do that now Uh Do you want me to make this window a bit bigger? Let's see. See what I'm just doing over here It's a perfect balance between having enough space on the screen and you can be able to actually read it So Yeah, so it's very simple if you want to replace um non reactive non dynamic ui with dynamic ui All you do Is you just say where you want it to go. So like here ui output here And then just write as I say and I always write ui at the end like that And then all you need to do is you just need to move whatever you've got here Down to here So this will now go In an output function Output dollar sign date range ui This gets brandy ui normal bracket curly bracket It just goes in there just hold up And that's it. Oh, I know is I have done something here. I supposed to kind of in an effort to illustrate you But this is still This is still not reactive. You can still actually run this at the top I suppose I was just trying to illustrate the point that you can carry out data operations Um But that's not arguably not a brilliant way of illustrating it because uh, actually that would still run in the ui But I'm just trying to show you the the kind of structure over really So let's just do that. Why not? So now it'll just look at the look at the range of the data Okay, let's just make sure we haven't broken it. Oh, we definitely have because there's an error. Oh, yeah Is that just a comma? Oh, no stop the thing first It's kind of interesting actually just to slightly go off Slight tangent so I mentioned before about writing or Not writing unique in the chat. I don't think shiny actually likes that very much. I don't know what exactly what the problem is But if you look up here, it says warning this selective input has a large number of options So I think what's happening is that that R is dumping the whole thing to that control and then that controls javascript or something is somehow Pulling through them and that's maybe not a good idea I'd have to I don't know enough about it, but maybe It doesn't like that and actually it will be slower in a larger more complicated application actually that would slow down So that's just an interesting Thing all these error messages here. I'm pretty sure just because of the deliberate mistake, but let's just check Yes, they are so you can see now they've disappeared um Yeah, so look, I mean here's some well, I'm sure you've probably seen some error messages maybe today already, but here's some Um Here's some shiny error messages. They're not They're just not very easy to read. It's hard. They've got lots of stuff in it that you don't know what it is and It's not always obvious I mean, it does at least say out book graph there to be fair. So you you slightly onto the right track there, aren't you? But I do think it it can be confusing Right, that's that everyone happy anybody not happy cool. Okay um Such that I mean, you know, that's pretty powerful tool out. So, um That's another good thing to know about Okay, so Some more ui type stuff um So this is um, this is not dynamic ui, but rather conditional ui So conditional um Conditional ui as it's called in in China called conditional panel It's very useful in an application like ours Let me just show you why where's it gone Is it here? I think I killed the application Sorry just a minute Yeah, so in this application, it's very useful to have conditional ui and the reason for that is because when you go to the map This control doesn't do anything at all You can press these buttons as much as you like And nothing will happen Because this map Shows all all of the organizations So this is not This is not this is kind of user interface territory It's never a good idea. Well, it's rarely a good idea to show a user a control In the current situation that they find themselves in doesn't work because they'll press it And be confused as to why it's not working So it's a good it can be good idea to clean that stuff out of the way So they're only looking they're only ever looking at stuff that does something like if this button's on the screen If you press it something will happen. It might not be interesting So for example, if I you know play around with this nothing fantastically amazingly interesting is going to happen If I wind it on a few months But something happens. It's different data So that's that's kind of a key principle really So that's what we're going to do So conditional panels are very easy. There's a function in our called conditional panel. Well in shiny. Sorry called conditional panel Um and It has two arguments basically one of them is a condition that you're testing for like is this true or not Um And the other one is just whatever you want to appear in the control So in this example, it would just be this this control As you can see would go inside the conditional panel Now this condition This is a little bit intimidating or I find a bit intimidating when I started with shiny because I was quite naive to web stuff back in those days It is quoted javascript So you in there you write javascript and you put quotation marks around it now If you don't know javascript that might sound a bit frightening And to be honest depending on what you're doing. It can be a bit confusing if I'm honest I've had to google javascript a couple of times to understand exactly how to express what I want But the simplest Form of it, which is what I want to show you is very simple So in its simplest form all you do is you just replace the the dollar sign with a dot And then just test for something So that will work that R and javascript are similar enough that that will work that you can write Import dot by import double equals Whatever and that will work If you're doing things like testing for membership or there's some other functions that don't really work under a bit confusing But you know, I advise you just to stay away from those as you're learning Um, and basically whenever this evaluates to true This will appear And whenever it evaluates to false it will disappear and obviously it will be dynamic So as you use it as that value becomes in and out of being true. It will appear and disappear um So that's what we're going to do um So Let's just pop this over here and We're going to move We're going to move the um The trust selector This thing here where you can select the organization you're interested in we're going to put that inside a conditional panel And we're going to test to see what the user's looking at. This is quite a common thing So when the user's looking at this we want them to see it but when they're looking at this we want them not to be able to see it um In order to do that we have to add one more thing to the application itself Which I didn't add earlier on just to avoid writing with arguments, but which uh can import Become important later on is we're going to add an argument to tab set panel That allows us to test for it And if i'm being completely honest, I always forget what it is Well, not always but often I think it's id We just have a quick look Yes, id So we're just going to write id Equals and just call it and it doesn't really matter what you call it tab set Just in case you got more than one tab set. That's all Just call it something And because you've done that that allows you to test for it Uh to test for what they're looking at um and um You need therefore to add so this has got an id Yes, precisely into the to the question of the chart. Yes, that's exactly that's exactly right. Yes Um, so we're just going to add another argument as well to the tab panels because we need to tell our what they're called Um, let me just use tab complete because I'm Yeah, it's value. I get the model of that. That's why I get confused So this is id this is value. So we're just going to call this graph I'm just going to call this map. Um, and that allows shiny to know what's what um, so Basically, it just becomes um Import dollar sign tab set will take values um So when um, I might just type on the screen so you can see it. So when you're looking at the graph import dollar sign tab set will equal Graph I don't know why I'm typing in the console that's got a cause r to go very strange. Let's not do that Let's just start your code window and when you're looking at input dollar sign map I mean when you're looking at the map input dollar sign map will be graph So that allows you to test for it. So you can now test these values and see. Oh, sorry. Oh, damn. Sorry. Sorry. Sorry Not gone to try and insert dollar sign tab set So you're always testing this one thing in sort of a tab set, but it takes different values depending on what you're looking at And then these are values that we've set Yeah, except I forgot to write value Try to do too much stuff at once So when we're looking at this input dollar sign tab, let's say equals graph when we're looking at this input dollar sign The tabs that equals map But as I say just to slightly confuse things We have to write it quoted javascript, but it's not as bad as if you don't speak Uh javascript. It's not as bad as it sounds. So let's just have a go down So all we're going to do is we're just going to add a conditional panel like that And we're going to write what the condition is condition equals quotes And then it's input dollar sign tab set equals uh Oh, hang on. I need to think about it. Do we want to show it or hide it? So when input dollar sign is true Is is graph we want to show it? Yes, it's graph, isn't it? Yeah um Like that condition equals input dollar sign input dot tab set equals graph And then we just pick up the whole thing it will just run out of the box. There's no need to change the code We just put it in there like that Just tiny my code up a bit. So it's taking the last room That's it. Let me just check see how I'm broken it Just correct the little mistake Right, so here it is and then we go to the map and it disappears So obviously your applications, you know, will be more complicated than this But this is a general principle of user interface design is only show them What they're interested in and what what what works? You left the quotations in the input. Oh here I did that deliberately Is that what you meant or did I just do something stupid? Oh, right? Yes. Good. That's a good question. I'm glad you asked so the reason is because um That's what this returns So you're setting value equal to a string so input dollar sign tab set will Equal this string Equally import dollar dollar sign tab set will equal map if you look at the other one So they are strings you very often that's the thing about shiny That's why I mentioned thinking about non-time evaluation lots of things are strings Because the stuff that um, the stuff that comes out of controls, you know, select import controls and stuff like that is all strings So that's why Cool. Okay, right. I'm assuming everyone's happy unless I hear otherwise um Right conditional panel. Okay. Cool. Right. Um So the next thing is No, I'm broken it But will it appear? Oh, no, I think you can't even I think you can I just did it that way because I just always do it. I'm just you know, I'm a I'm a creature habit. Let's find out Oh, it's it's trying to help me, but it's not helping me. It's confusing me. Yes like that. Let's try Yeah, that's all good. Yeah, don't mind Right. Okay. So the final thing is oh, I've just broken it again. So Uh, we're going to deal with this error message that we've been looking at So when it loads it looks like this. This is not a good experience. This is an R. You know, this is R talking to the user You don't really want R talking to the user because unless they speak R They're not going to what fasting variables are for one thing It's it's not a good experience. It also makes the application look like it's broken And that's the other thing I was saying before about shy development being different to normal development is that You know, when you're writing your own code, you've got a pretty whatever whether it's broken or not But your user doesn't so your user might think, ah, this is rubbish and just quit So we don't want this So what we're going to do instead there are two ways of dealing with this and they both work really well for the particular thing that they're designed for The first one is R a Q Which I'm guessing must mean require show. I'm sure it must have for a choir And so what that will do what require will do is it will it will not run a block of code until whatever is inside? It takes a valid value So it doesn't return anything or do anything or make any error messages or crash or hit a database. It does nothing at all And that can be incredibly useful because sometimes actually have to put these in because otherwise your application will just grind to it will actually get So this isn't necessarily just about good user experience. Sometimes it can stop your application from actually killing itself. Um, so that's really important Um, so that's require valet is a bit different valet will do it does exactly the same thing. It will it will draw the code to a screeching hold But it will also write nice our usage, which is more we want in this case. I'm going to show you both But I think it's it's Most people would agree that um, it'd be better if we said, you know, oh, you need to select a trust Rather than just having a blank screen, but we'll do it both ways. So Um, we're going to go on to the next code file now. So let me just make my window a bit big. Oh, maybe I don't need a window bigger I don't know. Let's see Um, okay any second is here Uh, I'm sorry, I should have said it didn't actually. Yeah, so The answers for the previous stuff that we were doing in this area as well. I forgot to mention that. Um And we've done it now, but yes, it there it was the whole time Um So we're only interested in now in these bits at the bottom Um, that are about, uh, either validating your code or requiring your code Either validating your code or requiring your code Um, so let's do require first. Let's pop this out again I think we probably will finish a little tiny bit early actually. Um We could maybe just have a quick chat if people sometimes want to ask about kind of hosting and like that kind of thing We could maybe have a quick chat about that at the end or you can all Just go about your days. Um, I think I'm not sure but I'm just giving you a pre warning um I think it's it's not as interactive as it often is this up this thing So I'm sort of amazed that I've done it all in three hours, but um, obviously everyone's sort of just cracking on so anyway Right, let's let's get rid of that horrible error message. So, um, let's do use require first because that's the simpler one so, um Basically, we're gonna want it Um Am I looking at the right code file? Let me make one over because it's confusing me um Yes, so we're gonna want it Oh, is there no Oh, I see Oh, of course because yeah, sorry. I was just I'm just working through there Yeah I'm just a bit confused because I wasn't sure where the filter even was because it's not in there But of course it's not in there because that goes to the map which doesn't filter by trust. It's down here. Yeah, of course, right So yeah, so when when Input dollar time trust does not have a value basically We don't want to run the plot because the plot will not run because it's got this filtering So it'll try and filter something that doesn't exist And fall over So we're just going to write req brackets and then we're going to write input dollar time trust um Just to briefly mention um So req, um It will check for what shiny calls like valid values and there are there are several sorts of um Well, I suppose they're more correctly called truthy values actually rather than valid values Um, I'm just thinking there's a list in here. So I'm just trying to find it for you Um, I'm sure it's in here somewhere Uh, oh, maybe it's it is truthy actually I think it is yeah, okay yes, so A value is truthy Unless it is one of these things. So this is what you're testing for really Most of them are pretty obvious Some of them are kind of things that you wouldn't really expect but you kind of when you see them you you couldn't understand why they're there So we're checking basically does import dollar sign trust equal anything at all except for false null empty string empty vector A non-empty vector that contains only missing values A logical vector that's all false an error Or an unclipped action button I don't really have time to talk about action buttons. That's a It's a way of allowing your user to decide when the application runs basically So it makes sense that you wait until they've clicked it and then run it. But I won't go into all that now So this is very useful this this is this is based on the is truthy function I really like the is truth function. I actually use it. I think outside of shiny. It's really cool Because whenever often when you're writing things you don't you can have strange things come through from database and stuff Okay, so sometimes it could be null or an empty string or just a load of like a lots of missing values all this kind of thing um And that can be very annoying to test for like is it null is it this is it the other blah blah blah And what this is truthy function allows you to do is just say If it's any of those i'm not interested. So it's false or null or what I don't care And that's very often works for whatever you want. Um so that's the is truthy function and It's sort of it's being called in the background essentially by require So requires checking that it's not one of those values And as you can see when the application is loaded it is one of those values. Um, I think An empty multiple select off from memory is null I'm not entirely sure. I wouldn't bet my life on it. It might be empty string, but I'm pretty sure it's null Um, so that's what we're testing for basically. Is it null? Is it an empty string? Is it false? um So if I run the application um We can see here now the error message has disappeared So it's not doing that annoying thing where it's confusing people with horrible red messages But equally well, um I'm gonna say this this function is incredibly useful, but not particularly in this case Uh, Clearly, I think validate is better here But just to stop the application from straight up, you know Either wasting time or crashing or doing something weird require can be really useful So now we've done that Let's let's do the same thing again with validate um So the validate code is just here So we're gonna get rid of this And we're gonna use validate and I've lost the thing now. Let's just move my window to the left So validate is a bit different because it actually contains the function itself And that function is need The reason why it includes need is because you could have multiple needs which again is very very helpful So you don't have to write loads and loads and loads of validates. You can just write one And you can say I need data of value value need trust of value value I need blah blah blah whatever you can test for as many things as you like And every time you write a need statement Um, you then write an error message that goes for the need statement So I'm only going to write one Um I can't what it's called now is it called true? Oh, yeah trust that's it So we just write so we write validate around the need and then we write the need and we say What do we need to be true or you know, what do we need to have a proper value in it input dollar sign trust? And if it doesn't what should we say to the user? Um, and then we might just write so please select trust And as I say you can have multiple of those um I don't really think I don't think I can do a sensible example to show you the multiple ones But just take my word for it that you can just put them on they've got a lot of different errors Oh, let's push them out. Why not? Let's just write one. That's a bit weird Uh need input date um Let's say greater than 2017 One and then let's put an error message Too much data So this is not really a particularly sensible example, but uh, We'll run at least I think Right now. Let's try to stop first Oh, yeah Oh, well, I just deleted all that was not That was not a sensible thing Oh, yeah, and I've got too many too many things Yeah, and it's just the thing I really like about that is actually we'll give you multiple at the same time Which I think is which I think is highly useful So at the moment it's saying there's two things. I'm not can't show you anything until you sort yourself out So I select a trust And now it's saying too much data, so I think well, okay Well, let's uh, I mean obviously this is not a sensible example as I mentioned, but let's um Let's just wind forward a bit to 2017 and there it is Yes, and as I say you can have as many of those as you like Um, as you can see it kind of slightly different examples these aren't they so this is just testing does an input container thing And this is testing the slightly more sophisticated example of Does that input meet some pre-specified criterion of I have like for example, you know what the date is or all that kind of thing um So you can obviously do some very very sophisticated things where and you do you might do this So for example, you might want an application that processes no more than 10 000 rows at a time Either because the user will have to wait too long it will crash the server or whatever Um, so you could do that you could have the application say i'm sorry. I can't process this as much data It's too much You'll have to constrain more and then I'll do it for you. That might be a good example of where you might have quite A couple of lines of code just checking that everything's um right bidding the missing ones and you know, whatever it might be Right, okay. That's what I don't require. So anything in the chat from anybody wants any more clarification about that Cool. Oh, yes. No, we've got this whole bit. Actually. I know this will take a while Yeah, no, I think you know, I don't know. We might finish slightly early, but no I had to be honest forgotten about this bit. This this bit will take a little while um Right, so we've done that we're going to stick with the ui um The next thing I want to show you is I want to show you how to lay out your own application So up till now we've concentrated on the um Sidebar layout Um, there are loads of other built-in functions that I don't really have time to talk about Uh, I will just briefly mention them at the end Um And there are like other whole entire way. So for example, there's a package called shiny dashboard. It's quite popular I use it a lot myself Um that makes shiny look a bit more called a modern and wizzy. Uh, so you might be interested in that um I'm not going to show you only the built-in stuff I'm going to show you how to do your own because I think it's a useful skill once you've got this skill You can sort of it's like a do-it-yourself type approach um and essentially And it's you know at its purest level it's quite simple So you lay out your whole application um with just two functions fluid rows Which stack things on top of each other And columns which divide each row into sections So you might have a row and then you say I've got Something here and something here and then another row and say this is like this and so on and so on and so on On each column can be made a different width And you can have as many columns as you like in one row, but they have to add up to 12 That's not shiny. That's this is all based on the bootstrap. Are you interested? This is all from a web Framework called bootstrap and that's where this concept of 12 comes from Um That's it. So let me show you So this is an example of a shiny application built entirely With with this thing and as I mentioned, it's got that fluid page thing. I mentioned that right at the beginning that does a lot of Stuff that you wanted to do so don't worry about too much about what's in there But if you miss that out, it will not work. It will be do something terrible um So as you can see here, I've got two rows One here and one here and they just appear stacked on top of each other And then each row is itself divided using this width argument like this So these are six and six because they got to 12 um and These are three and nine And you can see the output down here. So this is six wide and this is six wide You can see obviously it's divided on the middle then this is a thin one and this is a thick one There's a couple of salt to it, but I won't go into but that's basically it Uh and using those basics you could obviously build pretty much anything you want With a couple of there's a couple of little tweaks that you can make here and there Um, there's a question in the chat. What's the difference with well panel and box? um The similar that question is I don't know. I don't think box is a shiny argument though. Is that not shiny dashboard? Yes, I think you're probably thinking of shiny dashboard. Shiny dashboard has got that. Um Or maybe that's what you meant. Maybe you meant the whole time. Oh, I don't think I've even got it in store because I'm on the new version of our Yeah, here it is um Yeah, I mean they're very similar basically, uh, but while it's shiny dashboard and it's a box and the other one is Is just base shiny and again just to make this clear just if you're interested in them I don't I don't claim to be an expert at the library. I don't know much about it But I come I hear it hearing that doing shiny This well panel thing. This is also bootstrap. This is not shiny. This is this is this has been Also made in in the in the bootstrap web framework and they ported it in and it's just obviously this little gray Thing just like you kind of organize things a bit um Right, so that's how you do it Um, I'm assuming everyone's happy unless they say they're not um So what we're going to do now this is pretty much the end and I'm just going to talk a bit about like deployment and servers and all that kind of thing at the end So this is the last bit of shiny you're actually going to do and you just listen to me drone on a bit um We're going to we're going to lay we're going to bin the layout and start again uh Do it yourself. Um, so again, let's let's bring up the um Let's bring up the helping application stuff. It's not on this side. Is it No Of course the deployments at the end of session three. I need to bring up session three quickly. Yeah, that's fine. Yeah, cool. Okay, uh Right close this file We said no, what was it third bring up the third one a and e code third, which is just here I'm gonna pop it out again So It's just this basically It's just a fluid around two columns Uh, simple as that. Um So let's just do that. Let's make it work. So It's kind of go up to the ui So this Is the ui here We can leave that title panel. That'll that'll be fine. Um So this is the whole ui Uh, but we don't want sidebar there. We're going to get rid of sidebar layout and we're going to um, we're going to get rid of it This is again, it's slightly unnatural because now i'm going to Rewrite a ui in place. I don't think you'd normally do this You'd obviously just build it from scratch the way you wanted it in the first place But so that you have to forgive the slight unnaturalness of this, but i'm just going to just start typing underneath here. So We're going to pour this into this So the first thing to do is fluid write And as i mentioned, this is quite a simple example because they all have to be simple already So this is just going to be one row, but you can have you can stack them on top of each other So, you know, you can make this much more complicated than i'm showing you now But it just gets very faffing with you know, lots and lots of long code and all this kind of thing So with the whole thing that we realized with one row and the first column I think sidebar layout is roughly i'm not bothered to measure it. It's roughly three to nine. I think So it's going to write column three Meaning width equals three might be helpful actually if i just Write that just for your reference so you can see the arguments Um, and then in this column is going to go everything that was in the sidebar panel Uh, so all this stuff here Oh, no, we don't want the sidebar panel. We just want this don't we? So you just want these two functions a conditional panel and ui output are going to go Here looking a bit messy now isn't that's a bit better? Right, we're still right Yes, okay, so that's The fluid row with the first column in width equals three Now we're going to write a column comma and we're going to put another column column brackets nine comma And then this obviously is the outputs So now we're going to pick up The tab set and all pick up the whole thing piece mail And we're just going to put it in the column like that and i'm getting a horrible mess with brackets and whatnot No, I think we're right. So delete that That's the thing about shardy is brackets brackets can be Yeah, confusing I'll just put another return in there just to make it a bit simpler. Yeah, here we go So i'm pretty sure right. So that's right Incidentally, I can highly command rainbow. I don't if anyone's noticed I can hide if you haven't got rainbow parentheses They are super useful in shiny because you can get the big message like this Uh, so it's you know, if you haven't got activated I suggest you dig it out from the options and put it on because uh, it's not so important Literally when you write the article when you write shine applications, you can have a lot of brackets And like different types, you know, you have multiple curly brackets even so it can get a bit of a mess Um, and again, as I mentioned, don't forget just leave this for the page where it is. That's that's Doing a lot of work. That's invisible to you um And that's it. I think so let's just see if I broke it I've not had too many disasters. Actually, this has been quite a good one Um, oh, yeah, please like trust I will That our message is going to probably irritate me a bit but never mind. Uh, let's just Wind on a bit to there And there it is. So you can see it looks Very very very very very similar indeed. We've lost the well panel. You could put that back in if you want it to I haven't but I don't love it to be honest that gray box I think I well, is it ugly? I think ugly is probably putting a bit stronger But I don't love it myself, but you can put that back in if you want Um And that's it, but obviously yeah at the point of showing you that isn't so you can recreate the same thing The point of showing you that is that you can now make arbitrary user interfaces you can have massive inputs or you know like Lots of columns of outputs all along the side or you know, like you can do whatever you like as long as it adds up to 12 You can do what you like Right, I'm just going to recap So just to recap we've still got the fluid page. We've still got the title panel. They're both fine where they are We're going to define one fluid row. You can have more than one And they stack on top of each other and then we're just going to define using the width argument Adding up to 12 what proportion it gets and you just stick everything you want in here in there And it will just file down the screen And anything you want on the right hand side, obviously can be put here in this case. It's a tab set panel That's it. So that's a pretty powerful tool, right? Um, and I've used it many times to build all sorts of Strange things sometimes the the sidebar panel is a bit is a bit Limiting shall we say Right anything else anybody everyone okay? We've just got now we've we've you've successfully completed session two as well So How do you have a look at sessions for your own time? But I'm just going to skip right to the end Of session three because normally when I do this for a full day I do the um I talk about deployment I'm going to do that now for those of you who are interested some of you probably won't be at this stage, but some of you will so Um, I'll just tell you about some of my experiences to do Right. Oh, yeah. And just to mention actually what the third session is about just for your interest It's mainly about, um Our markdown Downloading our markdown files from shiny. This is an incredibly powerful tool. So do do dig into the code in in in session three if you're interested um Yeah, you can you can you know, you can download our markdown ports with arbitrary values in them So you can you know download your bit or your date or you know, whatever that is so that can be very very useful Uh, I cover shiny dashboard as well I go back and forth to whether I think that's a good idea or not. It's a cram package that that makes your application look different um Sometimes I think I shouldn't cover it because it's not really important because it's just basically a skin Um, but it is really nice and it does do some extra little things as well Um, and it is quite cool. So that's why it's in there. Um But if you're the kind of person that's happy making ugly shiny applications, you won't care about that bit um Right, so this is it. So we've got 17 minutes left of which I probably won't use all of them But I'm happy to kind of chat at the end um so deployment making things work and My experience about this is All in the in in britain in the nhs. I imagine there's people from all over the place I imagine there's lots of people from maraca. Maybe lots of people who are not um so What I say will be more or less relevant to you I suppose depending on your exact so you might work in an amazing place with all every, you know Data science gives more imaginable than deployment is all one click um But you might not Uh, so shiny does comment. It's worth saying. I mean, this is this is pretty amateur level But if you're just prototyping and testing, I always encourage people to do this Don't be put off by oh, we've got to get this license and server and you know, you do it lo-fi That can be a really good way of building Support for what you're doing and that's what I did. I was using china Can't be 10 years ago because I don't exist in 10 years. Whatever in version 0.6. I was using it Um, and I was doing all sorts of janky things that I wouldn't do now just to kind of show people So hey look at this is you know, you might want to kind of do more of this work um So there's a run github function. This is pretty amazing So you just type run github and you type the name of the repo and the name of the user um And it just into the console load the shiny library first and it will just download the code and the data from github and just run it um So if you just want to just show someone, you know, that's just for like Hey, you know, and this is obviously for only for people who are happy using r So if you want to just show someone something that's on your github just do that um There's another nice thing that that uh shiny includes as well, which is run url Uh, so you can use that with a zip. So you just get all your data and your code and whatever I'll bond little together in a zip stick it on a web server somewhere um And then you just write run url and just point to that resource and it will just download it unpack it and run it um Ditto run gist. I don't know if you're all familiar with gist It's like a little thing that on github where you can just show share like short files. It's not for big repos It's just for like one or two bits and pieces Um, and they all have an id that's numerical So you can just put that id in and it will automatically download the code and run that um And the other thing you can do, uh, I don't know how obvious this is or not I don't think it's completely obvious if you're working on some sort of networks environment or you know You're sharing a kind of you know, firewall environment or whatever you can just Dump it somewhere and just get people to run it themselves So if your users if your other users are our users, there are actually loads of really easy simple ways of sharing art with people And actually that's I think pretty well catered for in shiny and quite easy to do um As soon as you want to start interacting with people who are not our users obviously immediately gets more complicated Um, so there's shinyups.io. I'm just mentioning that because it exists. I've never used it I'm sure it's great, but I can't really say anything about it. That's the cloud service that our studio run Uh, I'm sure it's great, but I confess I've never ever used it. I have no idea Um, it's not great for us in you know I'm sure and some of you probably within the same session in terms of like healthcare type data because it's a cloud-based service And particular for us because it's a cloud-based service where the servers are in the us There's a very limited type of data we can put on there. We can only put the extremely safe demos on there. Nothing else Um So that's that um, if you want to authenticate users it gets more even more complicated again There is a there is a free way of doing this called shiny proxy that I'm again just mentioning it because it exists I don't know anything about it at all. I think it's java um I don't dare use it because if I said hey, let's use shiny proxy to authenticate our applications and it didn't work properly Um, then I would be in a lot of trouble So I don't do that, but you may be in a situation where you can or you want to investigate So do have a look if you if you want to um You can use proxy to authentication This is something I probably I guess I know slightly more about but to be honest. I have never done this either um What you can do instead if you've already got like a big web server type Like if it's all done already you've got all these people working on that kind of thing Then it's quite easy using Apache or nginx or I'm sure lots of other things too To just our proxy to authentication where you don't authenticate to the shiny application You authenticate to the web server that's in front of the shiny application So that's quite simple. So you just if you've already got people authenticating to a web server Just get them to authenticate and just don't let anybody through until they've authenticated and then all the shiny apps are behind So that's really only helpful if you've got that big kind of setup already, which I have to say I don't um But that obviously will work really really well and shiny is very adaptable to situations like that Um So that's that If you want to do it really simply Um, oh these stuff has to show in their age I suppose slightly because I think you certainly can't buy shiny pro anymore Uh, whether they even support it. I don't I don't know because we let we haven't used shiny pro for a long time either um As far as I know and I'm happy to be corrected. There is only really one game in town for authenticating people um In a sort of, you know super friendly cloud Well, not cloud necessarily, you know um Having a nice suite of applications basically that allows you to authenticate users to your shiny applications and that's our studio connect um So we use our studio connected my trust. Um, it's extremely brilliant So we used to use shiny pro back in the day um And and it was fine in terms of like It works as a server didn't crash or you know like it worked But the problem with it was it was just hard for the data scientists or well or what specifically me Because shiny pro you were really interacting with the linux server So you have to kind of ftp your files around and there was no help with kind of package dependencies either so if someone If someone changes their package version doesn't tell you and you're running different The server will only have one package on it So we had a big problem. Someone upgraded their tidy. I think it was me actually um And it just broke everything and we took us ages to figure out what the problem was Well connect doesn't do that because connect will save your exact package version information and deploy that So you press a button and it looks at your session and deploys that Um, and it will deploy different versions of it will deploy different versions of our different versions of package So the thing you deploy is the thing that's on your computer So that's very very useful and it's very easy to use It's so easy to use that the people on my team who really just don't know about this stuff at all Uh, can all use it quite happily. It's just basically just press a button once once it's been set up. It's all quite easy um And just to mention this difference just uh, it's probably obvious to to some or all of you. Um But obviously there are two main ways of attacking this problem One's in the cloud and one's behind the firewall um Being behind the firewall isn't necessarily more secure But your organization might think it is in the sense that certainly where I am There's a lot of sort of fear uncertainty and doubt about the cloud And I all you know, are people going to hack in and do it and stuff I'm not sure that really modern methods really bear that out um, but all of our stuff all of our sort of Patient type stuff, um is all behind the firewall because then it's just it's it's kind of safe and tucked away um So that can be another kind of upgrade route for you sometimes Perhaps you can get something working behind the firewall and then you can say well, you know, let's we want to kind of roll It's how big it really so let's get a proper, you know, safe authenticated cloud environment and let's do all that stuff That's the kind of development where you can work up to Um, I think that's everything department. Do I want to say anything else about? Um Uh, oh, yes, I'm just very very quickly again, probably fairly obvious, but just to The main ways you're going to be loading data in shiny is I mean, I think when you start you'll probably be loading csvn.r data There is a pins package That's very very useful, particularly using shiny if you're using our studio connect It allows you basically to have data resources That you just give them names and you just stick them on the server and then anyone can use them So I could make a data object and just call it, you know patient experience data And then anyone else in my team as long as they've got being in permission obviously can then just go to the server and just fetch it by the name Um, and so again, as I say before with shiny pro is more a case of dumping data files On the server in the file system. Um, whereas using the pins package with our studio connect Uh, it's a lot more of a nice clean experience where you just give the name of the object and it will just go and fetch it for you um And the other thing you can do of course is you can do sequel sequel obviously is quite performant if you use it properly So if you're using like if you're interacting using db plier Uh, it it will go pretty quickly because the computation is not being done on your server It's been doing on the sequel server. And so in my team we we do try as far as possible to Do proper hardcore data processing filtering that kind of thing on the sequel server Um through the db plier interface and then bring it back to the shiny session so we do as much as possible in sequel and then It's only the last bits that come over into the session and everyone and again I'm mentioning that because What I said before about shiny and you have to make sure your applications are quick and you have to make sure they don't take Up too much cpu and ram because you're sharing a server And all that kind of thing And that's just more exercises. Right. So that's it. So let's jump to our screen Um, you've survived so well done Um With seven minutes early, I'm very happy to um I mean, I would unmute you if I but I just think it's very complicated, isn't it? I mean, I suppose I could if anybody really wants to say something I can probably try and dig you up But there's quite a lot of you Um There's no way the self-contained shiny up to someone who's not an r user Yeah The short answer to that is no there and now I'm sorry there isn't It's it's a nuisance um It's a possible build a webface for me Yeah, absolutely Definitely, I'm not sure the shiny is the most natural language to do that in to be honest As I was saying right at the beginning about what isn't is an idiomatic in shiny, but you most certainly could do that. Yeah um So yeah, as I say do look at the github repo There's more I haven't done it all this is a full day course and I've compressed it into three hours So do do go and have a look you'll find me On twitter at chrispina. I'll just pop that in the chat Uh, you'll find me obviously on github. So do you know if you've got any questions or want to talk about shiny or anything at all? um, do Do let me know I'll just mention quickly my number one recommendation for when you get a bit better a bit better Is uh girl in with modules. I'll just put that in the chat as well I've got like a whole talk about how amazing golem is But there's no time for that today, but as you develop you might want to be uh, I haven't I haven't looked at that Uh, yes for that theme chair. This was my the lockdown present to myself It was not cheap to be honest, but it is very comfortable. I've fallen asleep And it's several times not while I'm working I hasten to add Um, yes, and I I I dearly love it. Oh, that's interesting. We're only shiny without a server. Oh, okay I haven't seen that so yeah I'll I'll I'll take a note of that for the next time we do this talk Interesting cool. Okay. Well, I think we're all done I was just hanging around just to see if there's any more questions, but I don't think there is But as I say do find me on twitter or wherever you'll uh, I'm around I think I can can I close the session? I think I'm co-host. I'm not sure I can actually