 Okay, we're live streaming now. Excellent, thank you. So welcome to EsmaCom for 2023, and this workshop on an introduction to our SHINee. This workshop is being live streamed to YouTube and has also got a group of participants taking part live with us on Zoom. So a very warm welcome to you all. If you have any questions for our presenters, you can ask them by the ES Hackathon Twitter account by commenting on the tweet about this workshop. You can also post on our dedicated Slack channel that was sent if you registered for the conference. You can post on the YouTube live stream and also if you're here on Zoom, you can ask the question in the Q&A facility. We do endeavour to answer all questions as soon as possible. We'd like to take your time to draw your attention to our Code of Conduct, which is available on the EsmaCom website at www.esmaCom.org. Our workshop presenter is Katelyn Hare from the University of Edinburgh and the Camarades Research Group. So over to you. Thanks. Thanks very much, Chris. Hopefully you can all see my screen. I'm just going to move this along slightly and we can get started. Here we go. So today I'm really happy to be here introducing our SHINee. This is very much an introductory workshop but hopefully everyone here has at least some experience with this webinar because it's going to make it a lot easier for you to understand what I'm talking about. So just a very brief introduction to where I'm coming from. So as Chris said, I'm a researcher at the University of Edinburgh and I'm a postdoc within the Camarades Research Group and we work on essentially large systematic reviews and meta-analyses of experiments and animal models of neurological diseases and I'm interested particularly in neurodegenerative disease so that's kind of where I do my systematic reviews. I also work on developing automated tools for evidence synthesis and developing pipelines to try and put all these tools together. And through my work in recent years I've developed quite a lot of SHINee apps because I think they're a really good way of communicating well I've actually got some use cases of where I've used SHINee apps in a few slides time so you'll see what I've used them for but I find them just a really useful way to sort of communicate with the wider research community without them having to learn ourselves. So this is just a few links here if you want to get in touch with me on Twitter and have a look at my GitHub page or the Camarades GitHub page as well hopefully in the chat soon there's going to be a link distributed which is a link to one of the GitHub repositories that we're going to use today for the workshop. So while I'm talking in this first half of the presentation if you could have a look at that and try to download the files that's going to be really helpful for later on if you want to follow along with what I'm talking about. So the workshop today this is how it's going to work essentially. I'm going to start off with some slides about what Shiny is, why you would want to use it then I'm going to go into a bit more detail on what the fundamental aspects of a Shiny app are so inputs, outputs all of that sort of stuff so that you understand the very basics of what a web application is and what a Shiny app is. Then we're going to create our very first Shiny app in R and you can follow along with that as well we're just going to be modifying the sort of boilerplate Shiny app that you get when you try to make one for the first time we're going to go through some example Shiny apps which I've made and they're available on that GitHub repository so we're going to walk through how I created them and different use cases for those apps I'm going to set you all a challenge as well building on from this workshop to create your very own app based on what you've learned on the workshop probably we won't have time for you to actually start working on that today so I sort of see that as an after workshop activity but let's see how much time we have and finally I'll have some more slides about the next steps you can take with Shiny and some considerations if you actually want to start making Shiny apps in the real world for your own research purposes so let's start off at the very beginning what is R Shiny so it's an R package that allows users to create an interactive web application using R code what it's actually doing in the background is it's calling things like HTML, JavaScript and CSS because that's actually what's building the website but you don't need to learn those languages which is the benefit of using Shiny you only need to understand R and how to write Shiny apps in R so that's a benefit especially for someone like me I don't come from a programming background at all so the idea of creating a website always felt impossible or like something that someone else would do and I'd never be able to do that so it's really great to use something like R Shiny and make that possible so why would you actually want to do this I just wanted to give three quick examples from my own research in places that I've used this so first of all quite often if you're performing something like a systematic review, metanalysis in our group quite often there can be hundreds of studies and all different animal models and all different treatments and there's actually so much data it's really hard to even put it all in a publication and you can share the data on open science framework or wherever you share your data but it's nice to be able to present it in a more visual way so that if someone is interested in exploring your data set further they could actually visually interact with it filter to get the data they're interested in and look at some nice plots so that's basically the first Shiny app I made was an app to visualise a systematic review data set and allow people to interrogate the data a little bit more one of the next Shiny apps I made was one to make evidence synthesis tool more accessible so I created a deduplication tool in R and then when I wanted to share it with some colleagues who didn't know R it just became very difficult and confusing to save myself future work I created a Shiny app that allowed people to run this tool without having to know R themselves so that's another example of where a Shiny app can be useful thirdly just to give maybe a slightly more advanced example we're now using Shiny apps in our group as resources so rather than just at the end of a systematic review when you're displaying your data now we have Shiny apps linked to SQL databases but query huge amounts of data and allow us they're actually like a starting point for our systematic reviews now so it's kind of went full circle and now we're actually using these as a resource to create more research in the future and this app alzheimer disease souls it's essentially systematic online living evidence summary of the literature in alzheimer disease animal models so it's got lots of visualizations it's a lot more complicated as an app and it's doing lots of more complicated things so it's just to kind of show you an idea of the scale of what you can do with a Shiny app so what is a web application really I was kind of when I was putting together this presentation I was trying to think about this because every website that you use is essentially a web application and what they're all basically doing is that they have a user interface or front end and that's the part that you're actually interacting with so whether it's Facebook or whatever website the part that you're clicking on is the user interface and that's what you're interacting with and essentially what happens is you click something and then you're showing something so you click a button and something happens or something pops up the other component is a server or back end and that's the actual sort of computer part in the background that's actually carrying out the computations or tasks based on those user inputs so those are the fundamental building blocks of what a web app is and these are also the two fundamental building blocks of a Shiny app so this is some Shiny app code here when you create your very first Shiny app it actually sort of comes in this sort of format so that you have something to start with and as you can see within this code the very first thing is you need to load the Shiny package and then it gives you these sort of two chunks of code UI, user interface and server so within the user interface you start off with quite often what's called a fluid page so this is like a function that is generating a page and within that you can put lots of arguments and then again in the server the server is actually a function so you can see input output session here as arguments and within that function you add all of the code relating to the computations so to illustrate this just to indicate what things will be in this UI chunk of code you've got things relating to the layout of the Shiny app the theme so what the website is going to look like the user inputs so the ways in which the user can actually interact with the web application and the outputs things like plots or tables or whatever is going to be displayed on the app and then in the server that's where all your computational your code to generate values or in the back end what's actually happening and you'll understand more about that as we go through hopefully so I wanted to just dive into slightly more detail what do I mean by layout so here is a very classic Shiny app layout where you have what's called a sidebar panel and then a main panel so essentially you can see here fluid page is kind of generating the page and then you have some other functions to generate the title to generate this layout and to generate this panel and this main panel there's alternative layout so you can have things like where instead of having the side panel you can generate a row on a web page and then have two columns of certain sizes you can generate another row and have some more columns so this is just a representation of this example web application and what the actual layout looks like and you can get more complicated as well so you can build Shiny apps that have multiple pages and Shiny apps that have multiple tabs within so you can see this one has a sidebar layout again but it's got sort of multiple tabs within the main panel showing the plots so it can get fairly complicated in terms of theme I just wanted to highlight it depends how much you care about this stuff for me like how Shiny app looks it's really fun to play around with that but not everyone cares about that but you can do lots of different things to make your Shiny app look nice and here's just an example of some different themes that you can use so Shiny app inputs what do I mean by that I mean ways that the user can interact so there's all sorts of different inputs available there's things like file inputs where you can upload a file to Shiny app there's text inputs there's checkboxes and radio buttons there's drop down options as well there's action buttons so when you click it it triggers something to happen there's also sliders so if you want to maybe slide between different years if you want a range of years for example or dates or something like that you can use a slider as well this is just a small number of inputs there's many more but it's just to give you an idea of the ways in which you can interact with the Shiny app in the code each input must have a name so this is really important they all have an identifier so this is just showing you example code for this radio buttons input so you can see the function is called radio buttons the very first part of this is radio which is not a very descriptive name but that is essentially the input identifier for this didn't need to click there button we've given it a label so we've called it radio buttons which is how this label comes about we've put in some choices so you can see there's a list here of different choices choice 1, choice 2, choice 3 and we've made it so that by default the selected value is 1 which is choice number 1 so then later we'll talk more about this later on so don't worry if it makes absolutely zero sense right now we can refer back to this input using input dollar sign radio because that's the name that's the name that we've given this input so as you can see because the default value is 1 here if we were to look at this value in the R code it would be equal to 1 and then we could use that for computations later on so that's kind of how it's linking together and every time a user clicks this button so if they click choice 2 then that input value would change to 2 and then that's the value that would be used in our computations briefly I just wanted to touch on different outputs so there's lots of different outputs and really nice visualizations you can make shiny apps so you can do all sorts of different plots you can have images as well you can have really nice looking maps and you can have tables again this is just a small selection similar to inputs each output must also have a name or an output sorry identifier so here this is from the user interface that we talked about in the last two slides about radio buttons so this is the input here if we were to create an output oh I thought that was in this slide but oh yeah okay so as you can see we've got radio buttons here and then the HR is just like it's essentially just generating this this line some of this stuff will be easier to you if you have done a bit of R Markdown so some of this stuff about like H3 for example maybe I should have said that is a sort of level of header and it's just about the size of the text that appears and this line for example things like this are kind of more familiar to you if you're used to R Markdown but that's what that is and then we have underneath here we have what's called verbatim text output which is just something that you'll come to know and it's just one form of text output and it's actually just it's outputting a value and let's see how that actually works in terms of the connection between the input and the output here in the server chunk of code here you can see we have this output value now that's relating to this verbatim text output value you'll see that's the same name that's been given and we're using this render print function which essentially is just printing out our input so you can see if this input radio is referring back to our radio buttons input which we said as a default it's set at one so we know the value of that input radio is one and this is basically just printing out one so this is kind of the most simple example of an input and then it reacts it changes that input value and it leads to an output so that's kind of a very basic understanding of how this concept of reactivity works in Shiny because essentially every time you change an input value the output will react to that and change based on that input value so oh computations yeah so that's just the computations happening in the server so all of this makes much more sense when you actually see it happening in an app so what I would say is the best thing to do if you're following along with this workshop open our studio now if you haven't already because we're going to create our very first Shiny app and just play around with the sort of boilerplate template that our studio gives you so if I move this along a little bit hopefully this will expand okay so hopefully you can see this and I'm going to go to file new file and then where are we shiny web app so here and this will create a Shiny web application to start with so you can give it a name it doesn't really matter so it used to be in the past quite often the user interface and the server were actually in different they would actually be in different R scripts but more commonly now people tend to have them all in one single R script so that's what we're going to do today but that's just what this option is of the single versus multiple file so we're going to stick with the single file and create this okay so this is our very first Shiny application and as I talked about earlier it's got this user interface bit of code and it's got this server part as well and just straight away we can actually run the app because it should work already and so I'm going to click this to run the Shiny application and it will open here so I can't actually even remember what this is I feel like it's earthquake or waiting time to next eruption can't remember but essentially you can change the number of bins in the histogram so you can move this slider input and you get a change in this output which is the histogram so that's what's happening here so you can play around with that so I'm going to close that again and have a look at the code in a little bit more detail oh I've just seen from the chat it's yeah guys are in Yellowstone yeah so that's what it is I knew it was something important but I just couldn't remember so if we have a look at the app code here you can see we've generated a fluid page that's this very first part of code in the user interface we've got a title I'm going to add Yellowstone here because that will help me remember and if we run that again you will see that has now updated the title so that's a very simple thing you can also do in your app to just add a bit more detail so I'm going to stop so that's the title panel that's fairly self explanatory now this is the sidebar layout that I was talking about so and again if all of this is new to you I would just encourage you to use the question mark and any of the functions to just get a bit more detail on what they actually mean and what the argument should be because it's when I first started learning Shiny it did feel almost like a different language actually from R because there's so many different functions and it does take a while to get your head around so keep looking at the individual functions to understand what's happening but essentially we're creating a sidebar layout with a sidebar panel and a main panel here and within that sidebar panel we have the slider and within the main panel we have a plot output so the slider input I mentioned earlier this is just a form of user input we've given it an identifier so let me have a look at this so you can see the very first argument is input ID so I'm actually going to write this here just so it's super clear so the input ID is bins because that's the name that R has given it then we've got the label here label number of bins for slider input you've got a minimum value and a maximum value and the final one here is the value that it starts at so the default value that's going to be shown on your app we also have this plot output and we'll talk a bit more about what's happening in the server so just generally with these sorts of inputs and outputs there is a standard sort of naming convention that tends to be for outputs it will be in the user interface it will be like text output, plot output HTML output, image output this sort of thing is usually how it's shown in the user interface and usually that's the function that you would use whereas in the server it's usually render whatever that output is going to be so here you can see we've got plot output and then we have render plot in the server and that's going to be the code that generates that plot so within here you can see it's generating bins and the bins are based on this input bins which is our if we go up here that is our input from the slider the slider input here so that's how it's how it's interacting with that value and actually if you want to look at this in more detail just so it's crystal clear what I quite often do is add a browser here so you may have used this in your rcoding in general it's very similar to a code break one of these here but it basically does the same thing where it will break the code and take you into this part of the function so that you can play around with the values so in fact actually I think I'll need to put it within here so that it actually stops in the right place so if I run that again you'll see it's allowed me to go into here and actually look at what's being generated so you can see if I just put input bins into the console you'll see it's coming out of priority because that is what we have here if I change this to 14 if I click continue just to make sure that's re-evaluated you will see if I put input bins here it's now 14 that's where it's getting that value that's where that's coming from so I'll stop that and get rid of this so one sort of simple thing I thought we could add into this app is as I said I like to make apps look nice and this is very ugly so let's add an extra input option to change the colour of the graph because that's going to be something we can add quite easily so how we're going to do that is if we go to within this sidebar panel here traditionally within these apps as well and the sidebar is kind of where you enter all of the inputs and then the main panel tends to be where you display the output so let's add it to that sidebar panel one thing I also didn't mention within the user interface is because it's all it's essentially using fluid page as the function and all of these bits are actually arguments within the user interface so you actually need commas in between basically everything you do in this UI section which is confusing initially so after we've finished with this slider input we'll need to have a comma and it's kind of up to you what kind of input you want to put in I think I'll probably put in radio buttons because that allows you to select between different options so let's do radio buttons and if we have a look at our what's within this radio button function you can see input IDs the first thing so let's give it an input ID color radio a little bit more descriptive than bins label I'm going to say pick a color pick a color choices so you can pick any colors you want I think I'll go for green red can't type red yellow there are some choices and that's really all we have to do well actually the final thing we have to do is set a default value so let's say select it which is going to be the default value equals green start off green so you'll see what's happened here already if we run the app again you'll see I've created this these radio buttons but they don't actually do anything yet so let's make them do something and to do that we would go down to this this this plot here this plot and within the histogram function you can see that the color is already dark gray so we don't want it to be that so we want to get rid of this and instead have input and what did we call our input color here we go so we've now changed this to our input value and if we run this again hopefully yes so now this is changing based on the colors that we select so that's just a very basic understanding of how reactivity works the input changes it's mentioned in this this part of the server where we're rendering the plot every time this changes this whole bit of code basically gets run again and it recalculates and then the plot is regenerated so that's what's happening here so now I want to go a little bit more detailed and to describe essentially the progression of an app for a specific reason so this is going to be a use case and if you I don't know if it's in the chat again we should could we post that in the chat let me see I don't think it's there yet but essentially I have a github repository which I'd really like you to download the R code from it depends if you feel comfortable cloning the repository I don't know how you feel about github you can also go on and just download the files individually so it's available here let me have also send it in case that helps just put it in the chat yes I will do that and it's on twitter and slack as well I don't know if it's sent on youtube because youtube seems to not like links but it's everywhere else perfect yeah I just can see the chat there that's perfect great so hopefully you can download that again if you don't feel great about github you can copy this or you can download the individual files you don't need to clone it depends how you feel about github so while you do that let me just talk briefly about this again okay so this is going to be a data set about dogs now you may or may not like dogs but the reality is I think my reasoning behind this was first of all that it was inspired by a tidy Tuesday data set you may or may not be aware of tidy Tuesday but it's kind of like a weekly data visualisation thing in R where they post a data set and then people try to visualise it in different ways so I saw this one last year about dog breeds and their different characteristics and how popular different dog breeds were so that sort of inspired this I also found an additional data set with breed sizes from the American Kennel Club as well and I sort of combined these together to get a data set which I've called dogs.csd and I've given it all it had not great names before as well so I've kind of tidied up the name so that's the data set that we're going to be working with today and yeah here's the the repository and essentially my thought was that a lot of people got dogs recently maybe during COVID or during lockdown and including myself and one of the things that I struggled with was what dog breed is best for me based on the characteristics and what I want in a pet so that's essentially what we're going to be working from today that's the kind of example app so hopefully you're able to get that from GitHub this is, I've just got a summary of the data set so you know what it looks like so essentially it's got these columns so it's got all the different breeds, it's got weights it's got basically ratings on how their personality traits fall on a spectrum so it's kind of like affectionate with family a five would mean the dog is like all over you and like up in your face and very affectionate and one would be that it doesn't really want to speak to you so that's the scale and that's kind of how the scale works for all of these all of these traits and then finally we have rankings as well in terms of popularity and how popular that dog was in different years that's what a data set looks like so the very first app that I wanted to go through was an app to help you choose a dog breed which is the problem that I sort of talked about earlier so the idea would be that the user inputs different dog traits and then the app is going to output a table of popular dogs with those traits so that's the idea in practical terms we're going to use a checkbox for different breed sizes so small dogs, medium dogs and we're going to have a select input for different coat types and sliders for the personality traits and then we're going to use the data table package which you may or may not have heard of but essentially this is going to generate a table on the Shiny app and it's going to show the top dog breed so let's get into that so if you have a look hopefully if you have the files here this is referring to app number one so let's move this along a bit okay so here's our app the very first thing is we're going to load in some packages so for this if you don't have it installed I recommend installing DT which stands for data tables and that's going to be a package that we use Deplier, Shiny and GGplot2 which you hopefully have already the very first thing is we're going to read in the dog's data frame so I've already read it in so we've got it here now you'll notice that this is all before we actually start with the user interface so this is kind of it's described as the global sort of session so it's basically stuff that's going to happen before anything else and quite often you would read in data at this point unless you want something to be read in when a user does something but we need this data right from the very start of our app which is why it's kind of outside of the reactive context it's right at the very beginning we're reading in this data frame so again we're going to have a fluid page that's going to be our how we start off the user interface we're going to have a title again using the title panel function dog breed this is what I've called this app feel free to rename again we're going to stick with the sidebar layout because that's what we've been familiar with so far this time we're going to use a checkbox group input so let me show you so checkbox group input essentially it's a group of checkboxes so you can have just one checkbox if you want a yes or no and this is just another sort of input that's got multiple checkbox options and then we have what's called a select input which is kind of a drop down option and as you can see both of these are very familiar so they both have an input ID they've both got labels they've got choices and they've got a selected option as the default that's going to appear and in this select output one I have to define so you'll see if I have a look at the arguments you also have to define whether you're allowed to select multiple which is what this argument here is so I've put that to true because I want people to be able to pick a couple of different options and this is for the type of dog coat for example and then we have a header again H4 the biggest header is H1 just for your reference the higher number you get the smaller the text is and this is going to be personality traits I've got some descriptive text about that as well and then we have some sliders so this is the same as our initial app earlier on with sliders where we have an input ID again a label again minimum maximum value and the value that's going to be there initially and the slight difference I guess versus earlier is that this is a range now so it's going from one to three rather than just a single value because that makes most sense for this particular app so the final thing I want to point out is in this main panel we've got a data table output showing the most popular dogs but for the moment I'm actually just going to comment out the server just so you can actually see what the app looks like without going into the reactive elements of it so yeah so as you can see that's our checkbox group input that's our select input so you can remove these add them back in and here are sliders as well here we go okay so let's bring the server back and talk about this a little bit more so I'm going to add a browser here again just so that we can have a look at this in a bit more detail and see what's going on and then we'll discuss what's happening so let's run this again okay get into here okay so essentially what I want this app to do is based on these input values I want it to filter that dogs data frame that I've brought in and I want it to then display that in a table so that's what's going on here so this is essentially filtering all of these columns to be greater than or equal to and I'll explain this the first input on this slider so if we look at open this level you can see at the moment it goes from one to three so if we have a look at this input open this level let's have a look you can see that's actually what's contained within it so there's really two elements there there's one and there's three so that's why when I'm filtering I'm saying I want it to be greater than or equal to the first one and then I also want it to be less than or equal to the second one because I want it to be between one and three so hopefully that makes sense but that's what all these filters are doing I'm also filtering so that the size category is within the input size so remember that's our checkbox group input and we also have the coat input and that is filtered here so we've got the coat type input coat we're selecting the two columns of interest arranging them by the ranking so number one is like the most popular dog and number 200 is the least popular and then we're displaying it in a data table so let's run this so you can see how it looks filter that we've got 62 dogs that meet that criteria and then we're going to render a data table and you can see it in this viewer how that table looks there's a few different reasons for using data table it has a lot of customization options which I won't go into today but you can do lots of cool stuff with a data table it's actually originally it's a javascript library that's been adapted for shiny apps and R so it's got some advanced features over other tables you can sort by columns as well so you can arrange by alphabetical order you can search for things it's got page donation as you can see so there's lots of reasons but that's why I'm using this data table function yeah that's and I've set the page length to 10 originally but you can change it to 20 if you want to see more breeds on the same page so let's see how this actually functions I'm going to remove the browser just so that we can actually look at this hopefully yes okay so that's it functioning as expected so we can look at we can move these sliders oh there's no dogs in that category you can move these sliders and see which dogs meet your criteria although I have to say with all of this dogs are you really can decide based on this so please do not use this app for choosing a dog because they're all different and you have no idea what you're going to get but anyway it is quite fun to look at okay so that's our sort of simple app I'm going to close all of these um tabs and stop it running hopefully it doesn't want to stop running that's great it should stop running but I might have to I might have to terminate it it's not happy for some reason okay that's fine it will come back hopefully in the meantime while that's hopefully sorting itself out uh yes just terminate um let me move this along so the second app we're going to make is on the same theme but we're going to be comparing two or three different dog breeds so it's kind of a different use case so rather than putting in the traits that we want our dog to have we are putting in a few different choices and then comparing them um we just had the sorry Caitlin um we just had a question on um Slack so um it's actually two questions um so one is um explain a bit more in detail the link between input and output ID on the server side and the app side so I think it's just go through that again um and the second question is documentation for the different inputs we can have so sometimes slider sometimes selection um I can I can dig up the documentation and post the link in the chat while you're while you're talking through the first question if you want and question three was um will you always use the fluid page in the UI input okay um yeah all really good questions um so I guess yeah Chris if you could post the link to all the different inputs because essentially there's like a page that has all this information and I always have to look at that page to remember which and like I never remember any of this so um yeah there is a lot of documentation on that and it's more about just knowing oh I think there's an input that does this and then you find the code for it um for the inputs and outputs so um I'll try and go through that again but let me know if there's if I'm not being specific enough because I'm really sorry I don't know why this is like decided to crash at this exact time let me um let me refresh the page actually and see if I can get it back functional I don't know why this is randomly oh dear give me a second um this is a slight like I think we've uh we've maybe lost Caitlyn um so bear with us while we try and get her back um I'm assuming her insets come down or something um so just bear with us um I will try and answer some of those questions while Caitlyn's um am I back now you're back okay sorry about that no that's fine okay so I wanted to talk a little bit more you need to share your screen again oh of course yes that's the main thing um okay entire screen there we go let's find the shiny documentation okay um so yeah inputs and outputs let me know if this um still doesn't make sense because I'm happy to explain in more detail but um the question referred to input IDs and output IDs is that right Chris? yes it was what was the link between between them two yeah okay so essentially every input must have an ID and every output must have an ID so you can see here um within this app we've got input ID size for the um the checkbox group input and then for the select input for the different dog quotes like curly blah blah um we have an input ID of quote and I've just made this up this is just my own personal like ID for this um so you make these up and then the same for the sliders so they all have input IDs and then in the data table output and this is maybe what I didn't didn't explain is this also has an input ID so let me um let me stop this have a look at data table output and you'll be able to see go come on oh okay it doesn't actually have it has it links you to the website on it um but essentially I do that maybe oh yeah this shows you the arguments a bit better so you'll see there's an output ID so it's um essentially the same you have to give them an ID for all the inputs and outputs so that when you are in the server you can refer to them that's really the whole reason behind it so you can refer back to them so um I'll actually put that in here because it's not super clear so that's the output ID pop table or popularity table and that's that's just what I've chosen to call it and there's other options obviously you can change things like the width the height all sorts of other things um but I'm just going to stick with this for now and then if we go to the server you'll see that I refer to this with output dollar sign pop table so that's basically saying for this output I'm going to render a data table um that's basically like how that is referred to here and you can see the input is referred to in the same way with the input and then dollar sign and the input ID so hopefully that makes slightly more sense in terms of how they are connected but let me know if it doesn't um the third question was about the fluid page yeah so it's not the only it's not like the only way I don't think because you can get really complicated apps that um use different um how would you describe it I have some slides on it later um like you have things like shiny dashboards and I'll discuss more later but it's essentially different frameworks for writing um shiny apps so they definitely don't all start with this um fluid page but I think the the apps that we're going to be talking about today do because that's just generating generating a simple page and then you can still within that customize the layout so whether it's a sidebar layout or the fluid layout I was talking about earlier with the fluid rows and the columns and all of that sort of stuff so um it's definitely all you need to know about initially because it can get you a really uh a really long way um and there's one one more question from someone else um so it said um a mutually dependent select input to filter a data set so this person uses select eyes group ui but are there any different or easier methods um select eyes group ui that is I think do you mean on the shiny widgets packet I think on the shiny widget yeah yeah you're saying is there any better ones versus that uh yeah in order to have a mutually dependent select input to fight uh filter a data set so I'm guessing one that um and sorry you might need to clarify this if you're watching um but I'm guessing that's one that um will decrease the available inputs if you've your other filters have oh like it it changes based on your other inputs yeah yeah there there are different ways to do that um I have some slides on it later but essentially um you can update the options that are available within different sliders within different inputs sorry so like the choices um at the moment we've specified them manually and we've said we want it to be and I maybe should have explained this but um like we want the choices here to be unique dog coat type so if I just print that like that's what we want the choices to be or you can type them in but there are options where the choices can be reactive so that's maybe something to point out but we're not going to get into that yet but that that is an option so there's lots of stuff you can do here to make it more um dependent on on various things like if you said yes to an earlier input that's going to affect a later a later one thank you I think that's it for the questions we've got so far okay um let's move on to app number two which has uh introduces another concept so yes as I said app number two is going to compare different dog breeds um it's going to have an input of multiple um breeds and then it's going to have three visualizations about traits so if we have a look at this uh we're going to have another select input um we're going to have uh unique dog breeds as our choices we're going to select two of them as well and so that's what this is basically so that the app starts with something there that's the reason so it's going to start with these two breeds and you're going to be allowed to pick multiple as well uh within the main panel this time we're going to have three plot outputs so you can see here um output ID equals personality um oh not in tab panel sorry that's me getting confused so there's a couple of things going on here so the first thing is within the main panel I've also added um a tab set panel so this is basically and um let me get rid of the server for a second so I can show you this um hopefully this still works a bit so we've got the sidebar but we've got um I just wanted to sort of illustrate a slightly different layout option so you can see here we've got um what's called a tab set panel which is the thing I mentioned earlier in the slide where you can have like multiple tabs within the one um kind of bit of the page essentially and that's what's happening here so we've got three different tabs that at the moment don't show anything but they're going to um so within the first and another thing that I just want to point out as I'm going through this there's so many brackets involved and that's like the biggest the biggest mistake I make all the time in shiny is like making sure all the brackets are closed is just it's just a nightmare um you'll see there's a lot there's a lot of brackets even for a relatively simple app because each thing is a function within a function within a function um but you do get used to it um so within this main panel you'll see I've got this tab set panel and then I've got three panels and these are essentially um you'll hopefully see if I um have a look at the tab panel um function you'll see these are the titles of each of the panels and then within them I've got a plot output and I've got three different plot outputs as you can see with this output ID for the first one radar personality which will make more sense in a minute output ID for the second one bar characteristics it's not actually a bar plot so I don't know why I called it that but that's that's what I've called it um output ID equals popularity for the third one um and I've specified some heights and widths as well of just like how how big these outputs should be so that's that's what's in here so if we move over to the server a couple of things going on here um so what do we want we want to change these outputs based on this breed selection and if we think back to what we just did in the previous app what we did was based on the traits we we filtered the dog data frame and then we used it for our table that's what we did so we could do that here um we could and this is within the radar outputs it's going to generate a radar plot um render plot we're quoting it with output radar personality here which links back to um this plot output here that's what that's what we're doing um so what we could do is we could um get the dog data frame we could filter it with the breed that's in input breed because that is our input ID for this select input so we could do that um and then we could um ignore that just now look within this radar radar plot part so we could do that then we could use that to make the radar plot so that sort of makes sense the issue that we have is and here all that's happening is we're just um getting specific columns that are of interest to the radar plot code which you don't really need to know um for this shiny tutorial but this is just waiting a radar plot um so that's one way to do it the issue is that we have three different plots here so we have I'm just going to remove this again so that I don't forget we have we're going to have a radar plot we're going to have a um bar it's actually a lollipop plot and we're going to have a um a line graph showing the popularity over time so what it means is like we'd have to do that we're going to have a frame filtering process taking the dog's data frame filtering to only include certain breeds three times so it doesn't when you think about it that way it doesn't make an awful lot of sense to do that um and there is an alternative which I just want to um to point out so we can use something called a reactive expression so a reactive expression is essentially something it could be an object and it essentially responds to changes in input so the code within a reactive expression will update as soon as the relevant input changes so similar to all of this stuff with the plots um you know rendering a plot output this in itself is um reacting to changes in input but we can have a step before then with the data so that it responds to changes in input and then we can actually look within this um these render plot functions and I've got a diagram that hopefully will explain this um in a bit more detail but this is really useful so that you don't have to recalculate an output each time and input changes because um just from a computational perspective if we have to do this filtering three times here it just it doesn't really make sense um because we want all three plots to be reading from the same they're all going to be doing the same thing with the same data they're just going to be generating different plots from it so if we look at this oh no I want to change these slides if we think about an input so that's our our breed selection in our sort of old way of doing things what we have to do with that input is we'd have to do three separate computations and then those three separate computations would lead to three different plots all these three computations are basically doing the same thing until the point that it's used by the plot but um yeah this is a very it's going to take more work to do this essentially what we could do instead is when an input changes we could have a reactive expression which is one computation so if we imagine it will basically create a data frame that will have those two um those two breeds selected and then we can use that within our outputs to generate the plots so it's removing a couple of extra computations that we don't need so let's have a look at this in practice um over here I move this over again so you can see um so this was our our old option which is not a good option instead the start of the server code here I've put this reactive data frame essentially and what this is so you'll see it's using the reactive function and this reactive function is basically just creating a reactive expression that's what it's doing so you use these the opening brackets and you also use this curly bracket to sort of indicate reactivity so if we can have a look at this function and a bit more detail I think if it's going to let us see yeah so create a reactive expression um and there's a bit more detail about it here but what we're actually doing within it is we're taking the dog's um data set we're filtering it so the breed is within this input breed dropdown and that's all we're doing because that that's done everything that we actually need it to do so essentially this is for all intents and purposes it's basically like a data frame that's just filtered but we refer to it in a very special way going forward where we actually use it as though it's a function so you can see this selected dog's um double brackets that is referring back to this reactive data frame so that that's what's happening and so we can just use this reactive data frame now that's already being filtered for our plots so if we I'll remove this because this is not how we're going to do it if I browse here just so that you can see what's happening um I'll get rid of the other stuff just now so we don't need to think about it let's just look at the radar plot hopefully this works already let's see um okay so it's taken us into the code so you can see this selected dog's data frame if we have a look in the app you can see the two that are selected by default happen to be Belgian sheep dogs and I don't know what they look like um and French bulldogs so if we have a look at this selected dog it won't print out into the um into the console I don't think no so but if you assign it to an object then you can actually look at it and that's what I tend to do in these situations so we assign it to an object A then you can actually have a look at it and you can see it's basically just a filter data frame in this case with those two dogs so then we can use this we can select the relevant columns this doesn't matter so much because this is just creating a nice radar plot um and yeah let's have a look at that now in the app so I'll just get rid of this browser and let's have a look there so as you can see it's slightly so you can actually see it and so yeah that's basically it's filtered for those two dogs and it's generated this radar plot now when this is really useful is when we're going to use multiple plots as we are because we want all three of these to be using these two dog breeds so if we let's add another one in so this is our another render plot for bar characteristics which I refer to here so it's the second in the in this set of tabs again doesn't really matter what's going on here but I'm essentially just selecting the relevant columns from the selected dogs reactive data frame here and I'm just um yeah I do some extra stuff to change the names of things but it doesn't really matter and that will generate a lollipop plot showing the differences between between the dogs and then again popularity plot here is doing the same thing it just brings in the selected dogs already filtered data frame and generates a line plot so now you can see if we go to the app you can see all three of these now are using the same two dogs and if we change that so we can add in another one although it gets a little bit complicated to see add in Glush Cocker Spaniel because they're the best so now we can see three different dogs that's updated and that's updated so that's kind of how that works and how you can save yourself some computational time okay so that's I think that's all I wanted to say on this app um I don't know if there's any questions just now before we move on to the third app it might be a good time to ask them if there are any not seen any on Slack at the moment um there's none on Zoom and I don't think there's any on Twitter either so there is about a 15 second lag between YouTube and us so they pop up at some point um but I've not seen anything now so okay great I'd say carry on and I can always interrupt you if there's something pressing yes cool so that's with me two apps now um the third app is going to there's a question it's alright it came in while I was looking away can we get the link to the design choices um I don't know um you might want to clarify what you mean by that and we can um we can answer that yes um yeah I'm not 100% sure if you mean the code yes absolutely but I don't know if that's what you mean I guess it's just sort of maybe say that you know the default shiny do you mean those themes maybe oh different options oh sorry no that's me that's me I posted it on I posted it on Slack and not on Zoom sorry I will uh yeah yeah okay yeah all the different options because I feel like um in this talk I more just want to highlight like there are all these different options and then you can go away and pick you know all the options that are of interest so the link I sent includes all of the different built in shiny control widgets but there are more available through other packages possibly be on the scope of this but I don't know what Caitlin's going to do but um yeah there are there is a bit later on like leveling it up and not just using the default stuff so yeah okay so we've built two apps and this third app is going to basically put the first two together so hopefully you'll be familiar already with a lot of the code in it although it might look long when you first look at it so we're going to create a multi page app that also has a theme so it's going to look a little bit nicer oh I keep going on to the next slide so it should also look a little bit nicer because I hate the default shiny like page personally so we're going to merge the first two apps into one and we're going to make it look nice so if you enjoy that sort of thing this will be fun so I've opened up the third app here so this is app number three let's move that along a little bit so the first thing is we're going to create an app with two pages so and it's already done for us again because I didn't want to code at the same time and make a million typos so here's navbar page so this function again you can find this online there's a whole list of all the different layouts that you can use I'm just highlighting it and this is navbar page and it looks it actually looks like this little visual here where it puts different pages at the top with headers so if we have a look at what that function is actually doing you can see the first thing is the first argument is title and yeah it says create a page that contains a top level navigation bar and yeah the first thing is a title so dog breed loader is our title still I want to point out this is different to the previous app already remember we had title panel before that is gone now we have navbar page so that's the difference already here we also another difference is this tab panel so that comes from the navbar page so I if you look at the examples within this you'll see it's got the page and then tab panel is essentially the first page and then you have another tab panel and that would be the second page there's also extra things you can do like menus which gives like a drop down option on the page but we're not going to we don't have that many pages so we're just going to keep it simple so this is the first page explore dog breeds and that is essentially our first app so you'll recognise that with the side panel and the main panel again and then we've got page 2 where we compare our different dog breeds and that is our second app so we've just put them together the server we've just dumped all of the server code in here and may or may not be obvious at this point but the user interface it really matters the order of the code the server doesn't really matter too much the order of the code because it will just the app based on the inputs will look to the server and perform a computation when it needs it so it doesn't really need to be in a certain order so you don't need to worry too much about that I've also added a theme but I'm going to get rid of that so you can see it without the theme first so just pretend this isn't you pretend that's not there and we'll run the app let's see so now we have an app working oh I've also added images which I will discuss I just wanted to see what all the dogs look like so we can chat about how to do that but essentially other than that it's the same as the first app that we made and then this is the same as the second app that we made so we've just combined it into one and it already looks better and more sort of polished the next thing we're going to do is add in a theme and this is really easy for the basic set of themes so there's a package called shiny themes which is very well named and within that package there is a whole bunch of different themes here so you can just have a look at that website there's loads of documentation about it I think there's maybe 12 initial themes most of them are shown here I like the one called united for this app because and I don't actually know if it's shown here maybe there's 16 united basically it's kind of orange so I just like the look of it so let me show you what that looks like and then I'll change it and you can see what effect that has so all I've added here is within the fluid page you can see there is an argument for theme the default theme is no theme so here we've added theme equals shiny themes the shiny theme function and united I think within the function actually might list all the themes that are possible no it doesn't but you can have a look on this page and for all the oh there so these are all the themes that are available so let's run that and it looks much nicer and more polished already so that's one theme you can see it even changes the text and lots of other things as well let's do another one space lab great so that's another another option okay I'm going to keep this one because I like this one and okay so just another again minor point for people who like to make things look nice like me and if you want to add things in like icons that's very easy to do there is a package called icons and within that package you can essentially add icons so like at the very start of the page like this explore dog breeds for example in fact I'm not even that sure if it works at the very first header I can't recall if it does so let's put it here in this H2 breed characteristics title so if I put here icon paw and I know there's a paw icon which is why I'm able to do this but you can have a look at the actual function gives you a little bit more detail and there's a whole list of icons you can use let's have a look at that so it's added a paw there so that's a simple thing you can add to make your app a bit prettier and I didn't realize that images were in this app so I better explain that slightly and so as you can see in this data table here remember it's created with this render data table function we were filtering based on all the things and originally we had breed and 2020 ranking popularity ranking now I've added an image so this is actually in the dog's age frame just to point out and there is an image column and the I basically links to images of all the dogs so I added this in and you'll see if I don't have this last bit you'll see what happens because it's not as simple as it might appear initially so if I just leave it as it is in the data frame and add it to the data table it will appear like this which is not that useful and so what I did was I essentially mutated that and I pasted it in so this is HTML code I know basically nothing about HTML this was I actually ask chat GPT how do I add an image in HTML and it told me that this is what I should do so basically it's like a start tag and then you add the image link and then you can specify height and then you that you put an end tag there so this is something I didn't know how to do I just Googled it so but it really the reason for showing it is that it shows that you can integrate things like this into shiny apps you can add HTML code you can add CSS you can add JavaScript as well and if you don't know those things I do actually recommend asking chat GPT because it does seem to know about how to do basic things in HTML or JavaScript so that's what this is and then within the data table function a final thing to point out just relating to those images is I added the you'll see this in the package there's a parameter called escape and escape is relating to HTML and basically I don't want to escape it because I wanted to actually use that HTML code and generate an image so that's why escape is false here I've tried to document that so hopefully that makes sense and it gives you these really nice images which is oh no I've got the worst error it's possible to get okay I I just forgot to add this now we've got our nice images and we can look at all the dogs so that's nice and that's another reason for using data tables is it lets you do this kind of cool stuff that other tables don't always let you do okay so that I think that's it for the third app I do have a fourth app that has a little bit more more reactivity and a few more advanced features that I can go through now I don't know if there's any questions at this point Chris or whether I should just push on you're muted but that's really helpful isn't it sorry I've not got any I've been keeping an eye on Twitter there's none on Twitter at the moment none on Slack so let me check YouTube none on YouTube either so I have one I guess that might help clarify you know the little percent with the angle bracket and the percent thing what does that mean just for other purposes the thing that caused the error this okay yeah so I am very I use a lot of tidy various in my code so this is just the deployer pipe basically that's going between everything so you start off with this data frame and all of this is kind of like pipe together using a even explain it I'm like I don't explain the flyer I learned are only in tidy so actually all of the base functions I know nothing about and yeah that that's what this is basically and it's just the pipe and because it was broken here it just had no idea of what was where where this image and column came from so that's why it broke and I have a slide on this shortly but shiny is not that helpful when code breaks it doesn't tend to give you the most useful error messages so yeah that's something to be aware of as well and okay so that third app it looks better than and our earlier apps but there's actually two issues I wanted to fix so the first thing is that and you probably noticed like every time this changes that table calculates maybe that's a good thing maybe that's a bad thing if this was pulling from a database like every time you change the filters that would be really costly in terms of computation like every single time and what if you you actually want a very specific dog with like high energy levels and high barking tendencies why would you want that and you know you want specific filters and it you won't get to them all immediately and it doesn't make sense to update that quickly when you're still trying to configure your options so what would make more sense here is actually to have some sort of button to say like submit these options now filter the data frame and like get this and generate this output so that's what I want to add into this app the second thing I want to add in is we go to this compare dogs page there is a slight issue because if you add more than more than three it gets a little bit I mean the first thing is it gets very hard to interpret like there's too much going on and also because of the way that I've written the plot functions for these there aren't enough colors so it will actually come up with an error I think or it should it should come up with an error or these just won't generate at all but just sometimes what happens in shiny when there's a problem it doesn't tell you what the problem is but it just doesn't actually work so we don't okay there insufficient values in manual scale and that's actually talking about the color scale so basically these plots don't really work properly when you select more than three so we want to be able to tell the user that so that it doesn't they don't make this mistake so in this fourth app it's going to get slightly more complicated and the first thing I want to do is this to stop it recalculating every time the slider changes so let's think about that so we've got these slider inputs here remember and they are if we search for that open this level it's going to be in the server somewhere so it's here it's generating this rank table and you'll see what I've added here is is this isolate option so I just thought that so this was the old code here and this is the new code I've basically added this isolate which we can use to basically halt a reactive expression or to stop a dependency so at the moment what happens is every single time input changes and this is the old code every time this changed this whole thing would rerun again and you would get a new value and recalculate the table we want to stop that happening so we've added the isolate here and this isolates this input and stops it stops it recalculating based on that so if I just show you that first what that actually does just adding this to these inputs and make sure that nothing else comes up okay so now you'll see now I'm moving these and nothing is happening so it stops that reactivity okay so that's what the isolate function does so if we go back to this what we actually want is to add some sort of button or option so that users can say I'm done making my selection filter it now so we can do that in a few different ways but how we're going to do it is an action button so we've added it here so this is again one of the sort of standard inputs that you can use that you can read about and it's essentially generates a button similar to all the other inputs it has an input ID I've called it go button and it's got a label which I've said filter dogs that's going to appear now run that and see great so that's it doesn't work yet so now we need to make that actually do something so within this render data table function all we actually need to do is add this input go button in here somewhere and because we haven't isolated this it means that every single time the value of this input button changes then it's going to re-execute this table and that's basically what we want to happen so you can see you can see this in action let's have a look so every time so let's actually make some changes here first small dogs with high energy levels let's see and now that's filtered so you can see how that's maybe a bit nicer for someone to actually interact with as well yes so I think if you have any more questions about that I can go over it in more detail but that's essentially that was the main thing I wanted to show there it's just how to halt reactivity and how to get it to like run again based on something else so we're adding a dependency on the input go button and then that's going to make that all run basically okay the next thing I wanted to talk about was this feedback user feedback when they enter more than two more than three sorry breeds into that second part of the app so that the plots actually work so in that instance let's have a look at the radar plot here so how this works I mean there's a few different ways to do this again like everything is shiny but I thought we'd use the shiny feedback package so this is a package and it has a its main sort of function is this feedback warning and what that generates is something that you can see here so these are all feedback warnings so like this is a text input and if you type in a certain thing it comes up with this like warning symbol don't do that and tells you what's wrong this on lots of different inputs basically and tell it when a user does something that they're not supposed to do or enters a like I don't know letters into a text input into a numerical input or something like that it will come up with a warning and tell them what to do so that that's the thought behind this so how we actually do that in the code is within radar plot we can add you can see here we've got the shiny feedback feedback warning we have to refer to the input ID of the input that we're trying to warn on so remember it's the breed input that you select different breeds that's the one that we want to flash up with a warning and now the logic behind it is slightly more complicated so let me use the browser and actually get in here so you can actually understand what's happening and okay let's go to this bit right go back to the code okay so remember this input breed at the moment we've got dashings and French build dogs okay so let's just have a look at that great so how shiny feedback works is essentially it's asking for how do I explain this it's like a logic based on something and it has to be true or false like when this is true then show this warning basically that's how it's working and essentially it's checking is this true this more than three and I'll talk about what that is so I essentially generated an object called more than three and that object is when the length of input breed is greater than three so at the moment the length of input breed is two because there's just two dogs and but so for this whole thing length input breed greater than three is going to evaluate to false because it isn't greater than three false and if I add another one in so let's and couple of other dogs and let this reevaluate reevaluate okay now if I run this again length input breed it's going to be three oh just three oh sometimes you have to run it because it adds each one separately so now it should have added all four so let me run that again okay so now it's four which is definitely more than three so if I run this length input breed greater than three it's going to say true this time which means this more than three and object you'll see more than three it's going to equal true okay so that's just me creating an object with a logical value so now in this shiny feedback I've put in an input ID relating to to this basically and it's going to be shown when more than three is equal to true which in this case it is and then the text is going to say please select three or fewer fewer breeds to compare okay so let me show you how this works in action now hopefully I haven't forgotten to do anything else let's see so I'll add in some more dogs okay so I've added in four it's came up orange so please select three or fewer breeds to compare and it's kind of yeah signaling to the user that they need to do something and so that's just another way to bring in sort of more reactivity and more it just makes the app a bit more user friendly as well because they'll understand why it's why it's breaking essentially if they if they do something okay well wait so yeah so and that's me actually finished going through these apps I have a final app that's online if you want to have a look to I can share the link at some point but basically it's like the fifth version of this app and it just looks even slightly better than this and it's got one more plot and and it was just kind of to illustrate the progression of this app through different stages so hopefully that's been useful and now sort of coming away from this workshop I do have some more slides after this but I just want to set all of you a challenge now kind of leading on from this workshop not everyone likes dogs some people prepare cats I'm not one of those people but just for balance and to make things sort of fun going forward I have put a cats.csv data set in the GitHub repository and what I would love for you to do is to use this data set to build an app all about cats if you want to essentially using like similar logic to what I used you can use the dog apps as a sort of template to help you and like get some ideas the cats data set is actually quite similar to the dogs one and which is good like it's it's got similar and sort of sliding scales for different personality characteristics so I think it should be quite similar so you should be able to adapt some of these ideas but it just gives you a new data set to play with so use it to build an app and I change some of the inputs and outputs play around with themes and layouts and consider reactivity and user feedback and try to integrate some of these cool features that I've mentioned and that I'm going to mention in the next few slides and please also if you could share it that would be so great sort of coming away from this conference if you were to share it either somewhere on the Slack or on Twitter or however you want to share it it would be really cool to see all the different iterations of this app and yeah so I'd love to see that even though I don't like cats that much and please do that and try it out. I however have two cats so it would be more than happy to see all of your all of your cat filtering filtering apps yes you might be more pleased to see it I'm pleased to see the shiny in action but yeah you can take or leave the cats but yes some of you might like it more than the dog the dog one anyway okay so I've got a few more slides to finish up one important thing is about sharing your app with the world so if you're actually going to make this cat app you might want to actually share it somewhere. I personally don't have much expertise outside of shinyapps.io that's where I share all of my apps I know that you can you can use your own like web server you can also host them on github I think the easiest for a beginner though is probably to share them on shinyapps.io I've just taken a screenshot of the shinyapps and .io page so like if you just search google it you will end up on this page and you can sign up and it has step-by-step instructions so it's really really easy it'll just take like five minutes to fall through these instructions and then you can deploy it to a website and share it with the world and as long as your app isn't super complicated you can get away with the free version for a very long time unless you're in the future if you're like I don't know pulling in lots of data and it's really complicated you might need to upgrade to a paid version but for the cat app you can definitely get away with it being free so please do that I wanted to just touch briefly on debugging shiny I mean luckily I didn't have to do it too much today but it can be really challenging because as you probably realize with me going through the code it doesn't shiny isn't like an R script where everything is logical in order it jumps around so whenever you click something on the input or even when you navigate to a different page or you know a different part of the app it will go to the server and get that specific bit of code and then you know generate something and it can be very difficult to logically like even understand where to put a breakpoint in the code or where to put that browser option so it's just something that you get used to but it's really challenging definitely more so than debugging an R script error messages again are not always informative they don't always actually tell you what's wrong so some of the top tips I have are to run code outside of shiny first just to give an example so within the server here for example when I was creating this code if I go to maybe this one what's an easier one probably yeah this one's fine I guess this one where I'm filtering a data frame based on the inputs even this for example I quite often run this in a separate script or just run it within shiny but not in shiny and what I would do is like instead of having input open this level or whatever input you have I would just put a character value or whatever value you expect your input to take and just check that the actual code works and it's not something about your code that's what I tend to do all the time run these things with fake inputs basically I find that really useful another tip is to press this run app constantly because every single change that you make could break it and you don't want to be like what I've done in the past is you write loads of code and then you run it and it's broken and then you have no idea what point it broke I would say run the app every time you make some change to the code so that you don't end up in that situation because it's horrible and then you have to go back so many steps to try and work out what you've done I've already pointed out using break points and using the browser function which is really useful to kind of get into the code and see what's happening at certain points another thing is just very simple you can get the code to print out things so like here you can get it to print print the structure of the DF safe frame that we've created just to check that it has all the columns that you expect it to have and it will just print out into the console for you to look at while the app is running and this can be useful to understand like which bits are running before other bits because if something prints out first you're like that bit of the code is just run and then this bit of the code is run so I find that really useful either print or message for that another option is to use this so you can actually put it in the code let me get to a slightly simpler app than this one so let's go to this app if you type in options we react log equals true you put that in and then you run that app and then you press I think it's control F3 yeah so it like opens this thing which to be honest kind of terrifies me but some people find it really useful and you can basically it's became massive you can basically step through so from the very start of your code you can like step through each bit and like see I'm like not very good at using it as you can tell because I'm scared of it but yeah like the step here so you can step through what's actually happening so like for this population table population, popularity table sorry that was generated in the first app you can see like all the things that are going into it and when they come into the this is a really simple app but like with more complicated apps this sort of visualisation of when things are interacting and when things become what we'd call it is invalidated so like when reactive output is going to be changed based on an input all of that can be useful it just depends how you learn and what how you get to grips with the whole reactivity side of things so it might be helpful for you if you're quite a visual person and you want to understand all the connections so that's another option as well let's move that back over someone asked the question I sort of answered it on Zoom in the text but I thought I'd read it out someone said how to share your app and get a hub do you share only the code and I've said get hub itself can't host dynamic things you have to use something like shiny app but you can share the code on get hub and then people can download and run it themselves yeah that makes sense I have seen people share things where it's like I don't understand that maybe it wasn't a shiny app it only supports static file hosting so it's good for things like the package down instruction manuals that can be generated but it doesn't do things like shiny that need access to data I see yeah that makes sense yeah I mean I've only ever used shiny apps.io I think there are other options but I just stay away from them because I don't understand but yeah okay so these are just a few more slides we've only got 15 minutes left but these are just things to consider going forward I don't think you'll understand all the things I'm talking about here but it's more to just make you aware of the sort of things you can do with shiny and things to consider if you're going to start building shiny apps for your own purposes so the first thing is where are you going to store the data so we've slightly touched on this but depending what your data looks like if it's image files arbitrary data all sorts of different formats it can be lots of things you can store it somewhere like Dropbox and you can pull it into the shiny app that way you can use Amazon S3 or other I don't know if you can use Google Drive you probably can I haven't used it personally but I imagine that sort of thing you can use and link to it you can also so like for this dog app and your cat app shinyapps.io it does have some limit on storage for the data that you upload but these files are quite small so it should be totally fine so you can also have stuff like you can have files in your your filing system and your computer if you're running shiny app locally or if you're downloading to shinyapps.io if it's a small file like a small CSV or something you can just upload it with your shiny app if you have more structured data you could use Google Sheets is a good option for beginners who maybe don't know much about databases I've used Google Sheets before it's really easy to link to that using the Google Sheets for package link to SQL databases as well within shiny so that's another option and obviously I've never used this but I know that if you have sort of semi-structured data you can use other systems like MongoDB for example so there's lots of options that shiny can connect to for external data oh and this I just wanted to point this out this is a link to a really cool shiny app that sort of shows it shows all different data inputs and how they like come into shiny and how to like how to bring them into shiny in your code as well so I recommend having a look at that if you want to know more about different data storage options so how will you visualize the data I showed a couple of options today but there's so many plots and plotting libraries and all sorts of stuff that you can do I wanted to point out you can make really cool interactive maps with a package called leaflet it looks really you can like zoom in hover over and just lots of really cool things and another plotting library I use all the time is plotly which is similar to ggplot in a lot of ways in terms of the different types of plot that you can do but then you can hover over and interact with the plots a lot more than you can using just ggplot and so for example and this is maybe I can have it do I actually have it here because I was meant to shiney apps and all that one and Explorer this is like the final shiny app that I put online and from my work on this workshop you can see like I added this page at the end and this is a plotly graph just to show you the sort of stuff that you can do so like this is plotly and the difference is it's a bubble chart but you can hover over and you can have text that appears when you hover over as well and another cool thing just to show you quickly is you can also do things like click and get things to appear based on like whatever you've clicked so that's just to show you the benefits of using something like plotly over the more simple ggplot visuals an advantage of plotly as well is you can use what's called ggplotly which is a function that basically turns ggplotcode into interactive plotly code and that's what I did for that bubble plot like within the code and you'll see in the github repo this is app number 5 if you're interested I basically created a ggplot bubble plot and then use this ggplotly to transform it to an interactive plot so that's really easy and you don't need to learn any new functions within plotly to be able to start doing this cool so how can you level up your reactivity I just want to point out cool things you can do as you go forward with shiny I think it's just useful to know like this is possible you don't have to implement it straight away but you can do things like have plot clicks as inputs as I just showed in that app where you click in a dog photo comes up there's actually 4 different types of inputs from plots you can do click hover and brush and brush is more like where you like get square and like zoom in on a couple of things lots of options there and they can all be used as inputs and you can generate things from them in the server so they can be used for computations which is pretty cool in the data tables package you can use things like you can click the rows of the data table and that also can act as an input and be used in some computation later you can invalidate reactive things after a certain amount of time so for example if your app was connecting to some external database and maybe that database was changing every I don't know half an hour whatever amount of time every 5 minutes new data was there you can set it within the app using this invalidate later function like after a certain amount of time stop this this output and actually regenerate it based on the latest data so you can do things like that that can be very useful in certain cases you can perform computations under certain conditions so if you click this and click this or when you've done this specific action you can make something else happen so it can get really complicated in terms of the reactivity there's just a couple of functions there that you can use for that someone mentioned this earlier about updating the choices of things in a more reactive way so like in this app for example maybe if I was going to make it really good I would only click small dogs for example maybe there isn't a small dog with that's hairless this option wouldn't be there is what I'm trying to say so you can make it so that the inputs are reacting based on other inputs so it's kind of like if you click small maybe only three of the code types would be there because only these code types are available for small dogs so you can do that sort of thing using the update, select input or update whatever type of input and that actually is part of the server code which is kind of different but if you're interested in that have a look at those updating input choices you can also have lots of different things in terms of conditional user interface components so again when you click extra large dog maybe another option comes up I don't know I'm trying to think of something that would come up immediately basically after you click on an option another type of input would appear for example so you can do that sort of thing as well so there's conditional components that can appear based on your selections I've used that one on the Prisma Flow Diagram app so if someone says true to an option it adds another set of number boxes for example yes exactly that sort of thing that sort of thing is what it's useful for I just wanted to point out a couple of things a couple of resources so there's this shiny awesome github page I'll see if I can get a link to that or maybe you can Chris actually but it's basically this github repository of all these amazing shiny extensions and like ways to make your apps look really cool again if you're into that you should definitely have a look at this you can do really advanced themes as well I just wanted to point out those 12 or 16 themes are not all the themes that you can do you can make your own theme and there's also this bootstrap library package bslib I think it's called where they have more recent themes as well because the old themes are based on old bootstrap themes from quite a while ago so they've got more modern themes like this one's called minty I think and it's kind of a bit different very pastel colours so there's a whole other set of themes as part of that package or you can make your own theme from scratch there's loads of options there also just wanted to point out this shiny widgets package that I think someone also mentioned earlier I use this all the time because I don't like a lot of the defaults so you'll see like this button is a shiny widget action button rather than the default action button that we used earlier they basically have a lot of the inputs that we've discussed today but just like nicer versions of them so again if you're into that I recommend looking at this shiny widgets package because it uses the same syntax as well really as the traditional shiny input functions okay yeah just wanted to say there's loads of resources on all the stuff I talked about if you are interested in taking your shiny up the next step as well like adding css or html javascript all these other things there's loads of resources on that on the shiny website and as I mentioned earlier I have personally found asking chat gpt about basic things very useful for simple html things because I know actually nothing about that so I just wanted to briefly mention that there's other ways to build a shiny app there's whole sort of frameworks around building a shiny app like a dashboard and you can see there's the flex dashboard package and the shiny dashboard package and you can make apps that look sort of more like a professional dashboard you can have they essentially have like these boxes that you can put plots in or inputs so they look quite different to the more traditional shiny apps so it's just something you might want to be aware of as well to get into this a bit more how can you scale a shiny app this is probably a bit beyond what you're thinking about just now but it is quite cool because you can integrate things like Google Analytics so you can see how many people have been looking at your shiny app and using it that's something you can look into and it's fairly easy to implement you can use the Profiz package to look into your shiny app and see what's taking so long because when I first started making shiny apps I was using quite big data sets and it was taking a very long time to load so if you start having those sort of problems I recommend profiling it and trying to understand what computation is taking all the time you can also do things like you can cache which essentially is like for a given set of inputs you can essentially save the result of a computation and use it later so for the same two types of dog for example you can save the results from dashing and we're actually on the app already you can save the results from these two you can save the results of this plot if it took ages to generate this plot which it doesn't but if it did and then if a user entered those two again it would generate much quicker so you can do that sort of thing and there's loads of other things you can do to improve the performance as well so don't be disheartened if your shiny app takes forever initially because you can make it better just pointing out finally some introductory resources obviously the shiny website is like it has so much on there already it's really really useful I came across this github.io site from Lisa de Bruin in Glasgow it's really useful as well it goes through like each step in quite a lot of detail about how to build your first app and this book Mastering Shiny by Hadley Wickham is an essential read as well and that's available online that is the end of my slides I'm happy if there are any questions but I'm aware that we're like at the end of the session and please don't forget to build your own app and share it with us me and Chris because Chris also wants to see the app we just got a thank you thank you very much there's nothing on Slack and nothing on Twitter again so so I think we're okay for the questions perfect we'll just double check YouTube but we haven't had any coming so far there we go excellent we've got a couple of thank yous on Slack as well which is nice so I think that's yeah I think that's us done perfect well thanks very much for letting me talk about Shady for two errors that was really fun oh hang on I was thinking why is the Q&A starting lighting up but is everyone saying thank you bye excellent