 All right, well, I think we shall get started then. But thanks for joining us today. We're gonna talk about visualizing survival data, which is something I love to do away. So just before we get started, repeat a couple of things I may have said earlier and you may have missed. If you have questions, please drop them in the Q&A. We will definitely have time at the end and perhaps we can answer them while we're chatting live as well. I made a small little website using Korto for this webinar. And we can drop that in the chat, that URL. And it has links to the slides. And after the YouTube video has been posted, I'll add that here too. It'll be kind of like your one-stop shop for all of the slides and the recordings from today's webinar. So of course, over here on the left is the package websites link and then the slides link. So I think we can get started. So like I said, we're gonna be visualizing survival data today and we're gonna be using the GGSurfit package. So, and I think it's a really fantastic package for many reasons, which we will get into. All of this material is licensed in the Creative Commons Universal License. So check that out if you haven't seen that before. And I am Daniel Soberg here with you and I'm delighted to be here. So just quickly about me. I am a data scientist at Genentech. It's a member subsidiary of Roche, very large pharmaceutical company. And I've been working there for about six months now. Previous to working at Genentech, I was at the prostate cancer clinical trials consortium and a biostatistician at Memorial Sloan Kettering. That's where I spent most of my time, 13 years. And at Sloan Kettering, I wrote lots and lots and lots of papers. And so of course at a cancer center, we're always talking about time, two event analyses or survival analyses. So I think I published maybe 250, 300 papers and many, many, many of those papers use the methods that we're going to talk about today. And unfortunately, I didn't write the package until much later in my tenure there could have been really helpful for doing a lot of those analyses. I really enjoy writing our packages. I've never written a number of them. And I think that's good. So what we're going to cover today, so we're going to do a very, very brief outline or review of what survival analysis is or what survival data is. We're going to talk about Kaplan-Meier estimators, competing risks estimating, and then do some advanced topics in the GGSurfit package. So to begin, this is the briefest overview of survival analysis methods. So here are a couple of papers that have tutorials on survival analysis. I think they're really great because the entry point of these are at a tutorial level. So it's much easier to digest some of these. And I recommend to check them out if you want more information. So to begin, I'm going to just read a quote from this paper that I thought would summarize what survival data is quite well. Survival times are data that measure followup time from a defined starting point to the occurrence of a given event. For example, the time from the beginning to the end of a remission period or the time from the diagnosis of a disease to death, standard statistical techniques cannot usually be applied because the data are often censored. This is one of the most important part. Survival analysis has censored data. Survival time is described as censored when there is followup time, but the event that you're watching for has not yet occurred. So survival analysis or survival data appear in many, many fields and they go by different names. So there's survival analysis, which is how we call them in medicine typically, reliability analysis, duration analysis, event history analysis and time to event analysis. So a couple of common examples of survival data that you may have encountered in your work are time from, for example, surgery to death, time from the start of a treatment to progression of disease, time from HIV infection to development of AIDS and the list goes on. So the key here is the data that we're gonna be talking about today, we have some kind of starting point and then we're gonna follow participants or patients up until some endpoint of interest, whether that be recurrence of disease or death or some of these other examples. So here is a small little graph that's illustrating what time to event or survival data may look like when you have full follow up on every single patient. So this is a reputation of five patients who were all underwent some treatment and were following them from that treatment until they pass away and those little schools are when they actually pass away. So in this example, we are observing 100% of the follow up time. So if I wanted to summarize something like time from their treatment to their death, because I have full follow up on every single patient here, I can get the mean time to death, I can get the median time to death, I can do all of the standard things. That all works when you have full follow up. But what happens when I have the more common data where we have follow up on some patients for a year, for a month, for 10 years, but at the end of that follow up period, they may still be alive and we don't know into the future, of course, when that patient will pass away. We can use that observed amount of follow up time to still estimate what we're looking for, typically like the time to death, for example. So in this figure, again, the solid lines are the observed times but those dashed lines are unobserved. So we actually can never know when someone will actually die and that's why we have to use these survival methods. So in this case, we need to use survival analyses. The whole field of survival analyses was meant to handle situations like this. So your standard methods like calculating means, medians, percentiles for time to death or time to recurrence. In survival analysis, the most common method is going to be called the Kaplan-Meier estimator. So that's kind of our one-to-one link here. When you might have previously done a t-test to look at the difference in the time to death between two treatment groups, for example, you may do a t-test or a rank sum test or will coxon rank sum test. In survival analysis, you're going to do a log rank test and where previously you may have done something like a logistic regression or a linear regression. In survival analysis, you're going to do a cox proportional hazard regression. For each one of these cases, there are various methods to do these. So Kaplan-Meier and log rank and cox, those are just the three most common examples, but there are of course many, many, many more. So I guess let's just start. This is, probably you're familiar with this already, this is an illustration of a Kaplan-Meier estimator. In this case, this is, we are modeling recurrence-free survival, so time from some kind of surgery to recurrence. And we are looking at two groups, people who had a limited time since surgery and then people who had an extended time since surgery. And GG-Surfeit, the package really exists just because I just really felt that we needed a very, very simple way to make this super common figure that really just wasn't, I didn't feel like the existing tools were really doing it justice. And so we started making this package. So things I love about this package. So GG-Surfeit was written with proper GG-Plot2 geomes. So what does that mean? It means that you can use the GG-Surfeit geomes and you can also just weave them seamlessly with any GG-Plot function. You don't need to learn extra GG-Surfeit syntax if you wanna change the title, if you want to change the padding on your GG-Plot, on your figure, you don't need to, if you wanna add additional breaks, points, or change the theme of the figure, again, you don't need to learn any GG-Surfeit syntax for that, that all can be just handled directly with GG-Plot. You can modify the X-Axis in any way you want. So in some of the previous tools that existed, if you modified the padding on each side of the figure, the risk table below would not line up, for example. Another easy thing we can do with GG-Surfeit that wasn't previously possible was there was just very, very simple saving. Just take your figure, pass it to GG-Save, the GG-Plot function, and you can save your image in many, many formats. And these figures really just kind of come out and they are just ready to publish. So these are the things that really made me want to write GG-Surfeit, and I think the things that make it great. So we're going to be today using throughout the examples, a slight modification on the survival packages colon data set. The difference here is that this is called DF colon. It is exported from GG-Surfeit, and it is a tipple, and it has labels assigned to the columns, and some of the numeric values have been made into factors with factor levels defined as characters. So it's just a little bit more informative to look at when we are viewing our results. So we're going to be primarily concerned with these three columns in the DF colon data frame. It's going to be time, that is our time to disease recurrence, the status, did we observe you recurring? That's a one, yes or no? So in the zero would mean you are censored. So we did not observe your recurrence. And then surge is going to be that surgical timing, and that is going to be our stratifying variable here. So just to give you a quick, quick overview of this data frame, this is not how I would recommend summarizing this like in a publication, for example, in a journal, but it gives us analysts a quick overview of this. So when we're looking at the follow-up time, that time column, the median is 4.24, so about four years, right? And we have ranges from one to six years. 468 of the 929 participants in this data set did observe a recurrence. And about 73 had a limited time since surgery and about 27% had a extended time since surgery. So one group is larger than the other. So classically, if you needed to get a Kaplan-Meier estimator, you would use the survival package. It's really great, I love it, I use it all the time. And there's a function in the survival package called surfeit, and this syntax shows you how you would get the Kaplan-Meier estimators. And I'm showing you two very, very similar versions here. One from the survival package using the surfeit and one from gg-surfeit and a function called surfeit2. The API, what you're putting into that function is exactly the same between these two functions. And you can see that the results are exactly the same. So there must be some difference here, right? It's very, very small, it's very slight difference. The gg-surfeit2 function, it tracks the environment from which the call was made. And that allows us to accurately reconstruct or parse the call, the original call at any point post estimation. And because we know the environment from which it was called, we can go into, for example, the data frame that the call was made from and we can go looking for labels in there and we can go back and use that data to calculate p-values from the log-rank test, for example. Nearly every function in the gg-surfeit package will work perfectly well with both surfeit2 and surfeit from the survival package. However, when you use surfeit, there's going to be enhancements to what the defaults are, including those labels from the columns, for example, and there's a few other things. So I think that's, again, just it may look a little bit different because you're calling surfeit2 when you may be used to be calling surfeit, but really you can see here this Waldo comparison of surfeit object one and surfeit object two. You can see that they're exactly the same except for on that bit where it says names new, you can see there's an environment in that list and that is that calling environment that I was referring to. That point is a big technical, so if it doesn't make sense, don't worry. You don't need to know about it. That was really just for me, so I could do more for you as a default. So let's just get started. This is your very basic Kaplan-Meier plot, your estimator. So you see the first line, we're calling surfeit2 and we are getting our Kaplan-Meier estimates. That is just an object with all of these estimation inside of it and we are passing that object directly to ggsurfeit. That's our first ggsurfeit function, right? And I'm also adding a risk table. So three very, very simple common lines and you really done a lot of work here already. Your figure is really coming along. I think that's pretty great. So that's like the most basic example, but of course there's a lot of good here. It's like really simple code. The risk table, you got the risk table very easily. You can actually see even the x-axis label that was taken from the time variable in the data set. That is that columns label. So I recommend using labeled columns everywhere. I really love them. You can see that we're using our typical ggplot plus notation to add more things to that figure that's gonna come in handy much later, a bit later. But certainly there are a few things lacking here, right? The y-axis label, it says survival probability because like what else is it gonna say? That's actually not accurate. In this case, we're talking about recurrences. So that's not even accurate. And you can see here that we're showing the amount of area in the figure is where the data exists. So that goes from about 40% survival to 100% survival. But typically in a survival curve, you're gonna see zero to 100. The access padding here, you can see on the x-axis, for example, it's more extreme. There is quite a bit of space on the left and right-hand sides of that data. In this survival curve, I just don't like that much padding. And the x-axis typically has more tick marks than just these four shown. So I think this is a lovely generic ggplot default. But if I'm doing cap and liar figures, I would probably wanna do a little bit more. So let's, how can we change these few things? Let's just add two more lines. The first one is a ggsurfit command called scale ggsurfit. And what this is, it's just a simple wrapper for scale x continuous, a ggplot function, and scale y continuous to just make it a little bit more cap and liar-esque. And then the second function we're adding here is lab. That's a ggplot function. And I'm changing the y-axis label. So in this case, that scale ggsurfit has reduced the padding to something that looks a little bit nicer for survival curves. And the x-axis is reporting additional tick marks. So you can see it went from four tick marks all the way up to, I can't see very well, 10 tick marks. And at the same time, that risk table was updated to put numbers at each one of those tick marks. And we've also updated that y-axis. One thing I love about the package is not only can you seamlessly use ggplot function, like labs, you can use any one of the hundreds of extension packages. So this is gg-easy, a package that really kind of helps you remember the code a little bit better for modifying the themes, which can be a little bit complex in ggplot. So this gg-easy function, easy move legend top, moves our legend from the top. So previously here, it was below the figure above the risk table, you call that, and now the legend's on the top. So I'm just really illustrating here that it just works seamlessly with ggplot, but also any ggplot extension. I think that's super fantastic. I also wanted to illustrate that we do basic transformations here as well. So in the gg-surfit, I've added the argument type equals risk. And so instead of starting at 100% and showing down what my recurrence free probability is, I am now looking at the risk of recurrence. So starting at zero and climbing up as time goes on. So I touched on this just a moment ago, but I just wanted to make it very, very explicit here. So what is scale gg-surfit? It is a simple wrapper for scale y continuous, scale x continuous. These are the actual values. It changes the padding. That's the expand argument. It changes the limits to zero to one for the y-axis. And for the y-axis, you have actually a percent scale now on the y-axis for the labels. And for the x, we're asking for again, reduced padding. And then the number of breaks has been requested to be eight. Now, this is actually what happens for survival figures, but in the last example, we asked for risk. So in that case, it didn't set the limits to zero to one because you don't need to go all the way to 100% in a risk curve. So what scale gg-surfit is going to do is going to look at the context of what you've requested in your survival curve. And it's just going to give you a good default. One very important thing about using this function, I use this function every time I make the package and make a figure of survival, but scales in gg-plot really can't just be mixed and matched like they can a lot of the other functions in gg-plot. So if you're using scale gg-surfit, you cannot subsequently call scale x continuous or scale y continuous. The reason is that scales are not additive, rather they replace. So when I call scale gg-surfit, I'm changing, for example, the limits to be from zero to one. If I were to then subsequently call scale y continuous to do some other kind of modification, it's going to delete all of those other scales that I have specified and only do the ones that I specified in scale y continuous in that second call. So what you would need to do in that sense is pass those additional arguments that you would typically call, use to a separate call to scale x or scale y continuous and put them in the scale gg-surfit. So on that last line, you can see here that I'm calling scale gg-surfit and I'm saying x scales, I'm putting it in the list. I want my breaks to be from zero to nine and I'm explicitly saying that and that will add that argument to the scale x continuous argument rather than replacing all of the lovely defaults that we've sent with padding, number of breaks, all those other such things. So what essentially we're going to go through now is I think you've seen an example where you had a very simple survival analysis. You made a Kaplan-Meier estimator and you added a risk table and it looked good and honestly that's like 95% of what you need to do. So that's what really, if you have a takeaway, we've already covered it. We're going to spend the next, whatever time we have here to go through this going through some more advanced examples on how to do some more advanced customizations which is again, one of the best parts is that you can do these advanced customizations. So I'm just going to define a very basic default gg-surfit Kaplan-Meier curve here. You can see I'm starting with a surfeit to call. That's our Kaplan-Meier estimator. Going to do all the calculations for us. I'm then passing that to gg-surfit and I'm doing a function called add confidence intervals. So that's a gg-surfit function and what it's going to do is going to add a ribbon here around each of the groups with our confidence interval. And of course I'm adding a title here with the labs. And again, that's a ggplot function and I'm saying this is kind of our default. This is our base and I'm going to show you how we can modify it. So this looks like a lot of code because it is. ggplot code can get a little bit long if you're going to get really particular about exactly what you want your graph to look like. But again, what you're doing here is you're using the ggplot skills you already have. You're not learning new gg-surfit skills. You're just using your ggplot skills. If you've got them, I look them up all the time. They're not really inherent to me in every graph that I'm making. So here, again, we're just starting with that ggdefault that we just made and we are calling chord cartesian. So what that's going to do is going to zoom in. So previously we were looking at time up to nine plus year, I think a little bit past nine, but this is saying I want to zoom in to eight years only. So that's how you would do that in any ggplot function and that's how you do that here with gg-surfit as well. Rather than using scales, gg-surfit scales, I'm calling scale y continuous by myself and I'm essentially doing the same thing, but I just changed the padding a little bit and I'm doing something similar for scale x continuous. I don't want the default colors. So here I am changing the colors for my color and my fill aesthetics. I'm adding the minimal theme from ggplot and I am moving the legend to the bottom. For my guide, previously we had the two groups side by side. Here I'm saying I want those groups stacked into one column and then lastly I am adding a title. I'm changing the title from default to styled and I'm changing the y-axis title to percent survival and there it all is and here's our figure now. So you can see like that minimal theme, our legend is now in one column, our title's been updated, the colors have been updated, the label on the y-axis is now on the percent scale, the y-label is also updated, the y-axis title I should say. So again, this is really just illustrating, you can just use everything you already know about ggplot to make this figure do anything you want. Now this is actually not that hard to do without gg-surfit but where things get complicated very, very quickly is when you want a risk table. So let's talk about risk tables. So here is again our basic plot but this time we have a risk table and let's change it up a little bit. So here I'm applying this scale gg-surfit and I'm adding that risk table and so previously you saw that the risk table, oh I should let me tell you about the risk table what we're looking at here. We have our two stratification groups limited time since surgery and extended. So the, excuse me, the risk table is grouped by those stratum by default. So and it's showing you two rows. So you actually might commonly only see the number at risk but by default in gg-surfit what we do is we give you the number at risk and the cumulative number of events that have been observed which I think is a fantastic thing to be reporting along with your figures because it can be quite informative. I've seen a lot of Cap and Meyer figures that like quickly drop off to zero and you're like, wow, look at the event rates in that group that those people have really bad recurrence rates in who are getting that treatment. And if you look at the number of events you're like, oh well in that group you only had five people and four of them had the event really quickly. Okay, well that could mean that there's really bad recurrence rates in that. That group you really only have four or five people so that's not a lot of data. And that can be kind of obfuscated sometimes without reporting the number of events. So I highly recommend that you put the number of events in there by default. For a couple of years I was a statistical editor at European Urology and we did lots and lots of oncology there and we started adding these cumulative number of events counts to our Cap and Meyer figures when the office were able to do that for us and I think it just really increases the quality of the publication. But anyway for the takeaway from this graph is that it's the risk tables grouped by those stratifications. But if you prefer not to have a group by stratification you can group by risk table, okay? The risk table stats. So now you can see that the first section is the number at risk and the second section is the number of events and then on the left access there you have the stratification variables. So I think that that kind of functionality is really nice and super helpful. But when I'm looking at this I'm like, oh well the names of those groups are actually really long and they're actually not that nice to look at. So there is a function that you can add on top of that called add risk table symbol, strata symbol. So it will replace those long names with a symbol. And here I'm putting in a UTF-8 character for a circle and the color is going to match your legend. I see there's a question. What's so, let me see if I can answer that quickly. Does the GCSER4 package work with survey cox ph or survey weighted survival models? That's a great question and I'm not entirely sure. So this package is all about univariate analyses and not cox regression. So the answer about survey cox models I'm gonna just say no. And I don't know if I've ever had to create a weighted Kaplan-Meyer in R. Yeah, so I'm not sure about that, but that's a good question. If you would like to know the answer for sure what you can do is go onto the GitHub page and post a code example of how you would just do it outside of GGServeVit and I can then look to see if that would be compatible with GGServeVit and if it's not, we can put it in a future request and maybe something we can support in the future. So here we are seeing that we're using GGServeVit the Adverse Stable Stratas symbol to change that long text labeled to just be a simple circle with a color that matches the legend. How about cox-M-E? I am not sure. So again, that's a cox model and that is not what GGServeVit is all about. GGServeVit is about our univariate analyses. So I'm gonna assume no because even a regular cox model I'm not sure what illustration we're looking for in that situation. All right. Customizing our RISC table stats. So in addition to being able to group it differently or however you like or replace text long text labels with colors and symbols, you can also take that kind of like long table that had one section for at risk and one section for events and you can just kind of like group it onto one line. So you can see here on line three of the code that I'm saying RISC table stats equals and then I'm using some glue syntax some glue like syntax here. So I'm putting m.risk up front, right? And then in parentheses, I'm putting qm.event and you can check out the documentation for ad risk table. There's a couple of other statistics that you can put into the risk table and in this case, you can see the risk table has been updated to have the number at risk and then in parentheses right next to it the cumulative number of events. Let's talk quantiles. So this is a very common thing that we show on our cap and wire figures, right? So by default, we're going to often wanna report like the median survival or the median time to recurrence or death, for example. So you'll see a lot of these lines that have been drawn onto our cap and wire figures. And I just wanna show you that it's very easy to add that line here too. So with a quick call to add quantile you're going to, I've written it explicitly here that I'm putting it at the y value of 0.5 but that is the default as well. And you can see here that it's been added. You might be looking at this figure like, wait, there are two groups here, but there's only one line. If you zoom in on the red line right up there at nine years you can see that it actually doesn't quite ever meet 50% survival there and therefore there was no place to put the figure. So that group doesn't actually reach its median survival. You can also see here illustrating that there's another function in gg.surfeit called add sensor mark. I think for some smaller studies adding these censoring indications is useful. In my work, I typically worked with data sets that were a bit larger, including like this one I would say. And I don't really like seeing the censoring marks but it is something that is commonly seen in the literature. So we wanted to make sure that was possible as well. So quick call to add sensor mark adds our sensor markings. In addition to adding quantiles you can also add, for example, lines at five year survival. So I wanna know what five year survival recurrence rates are in each of those groups. So here I'm showing a line up from five years and then it goes off to the left to show that kind of that difference in survival between the two groups. And you can see here, we're gonna talk a little bit about this coming up but you can see in the add quantile call I'm adding line type equals solid, line width equals one, alpha equals 0.3. You'll see that those are just like actually very, very common arguments that are passed to GG plot geomes. And those all work seamlessly with GG surfeit. So let's talk a little bit about that. So each one of these GG surfeit functions that we're going to primarily be talking about is being powered by an underlying GG plot function. So GG surfeit is being powered by geom step. The add confidence intervals is being powered by geom ribbon and add sensor mark is geom point. So those are just points on a line, right? And add quantile, we're adding segments to our figure. Anything that geom step, geom ribbon, geom point, and geom segment except in those dot, dot, dot arguments can be passed to the GG surfeit function and we will just pass it directly to that GG plot function. So again, making it very, very simple to style your figure in pretty much limitless ways. So in this quick example at the bottom, I wanted to change the color. So I passed color to GG surfeit. Of course, I want the confidence interval to match that. So I'm going to pass that fill argument to make the same color. And I want my censoring marks to match the color. So I want to pass the color there as well. And I'm changing the default alpha, which I think is like around 50 or 80 or something. I'm making it entirely opaque here. So again, there are some defaults here, but you can override them very easily. And even when there are no defaults, you can add anything except to buy those underlying functions. You're also welcome to modify. Oh, looks like it did some cute highlighting, but I forgot to come in through. Some further risk table customization. So this is stuff I've actually never done myself, but I just want to show that just like you can style the primary GG plot, you can style the risk tables as well. So the risk tables are actually just simple calls to GM text where the numbers we're putting onto the plot area are just like the number at risk, the number of events, that kind of thing. So those are just separate GG plots entirely. So this theme argument is where you can just give pass a list of any number of GG plot calls, right? And so you don't like the font size, change the font size. You want something bolded, pass that here, we'll bold it. So that's just a GG plot, it accepts any GG plot customization there as well. There's an argument for risk table height, that's the first one listed here. 0.33 means that, oh, for this figure, I want a third of the plot area to be covered by my risk table and the remaining to be the primary plot. And here I'm increasing the font size of the statistics in the risk table. So just like the primary plot is super customizable, the risk table is also customizable. I like the defaults, I think they work well like nearly every single time. So I don't, I don't thoughts with this, but you may need to. So here's what you're looking at. You can see there's a bit more padding here in the risk table board bit. You can also see that the labels have been bolded as we requested in the previous slide as well. So here's another long example. So let's go through it step by step. We're gonna do type equals risk again, that's a transformation of our Kaplan-Meyer from starting at 100 and going down to zero, to starting at zero and going up to 100. We're changing our line width, we're adding a confidence interval, we're adding a risk table, but instead of using the default of only putting of putting the events and the number at risk, we just want the number at risk. I'm adding a strata symbol and I am giving it a specified size. I'm adding quantiles for five year recurrence rates. I want those lines, those line segments to be dotted and I want the line width to be 0.8. I'm adding sensory marks, I want them to be very, very light and giving them an alpha of 0.2, but I want them a little bit larger than the default. There's another function we haven't spoken about yet called add P value. You can see that this argument, caption equals log rank and then that glue syntax again in the curly brackets, P dot value, that is going to put the formatted P value from the log rank test in the figure's caption, okay? You can also, there are also options in the add P value function to put it in the body of the primary image if that's what you like to do. And then lastly, I'm changing some of the colors and adding a new title to my Y axis label. And here's the plot. I think it looks really great. So again, we're doing risk instead of survival. We have our dotted lines for five year survival recurrence rates. We have our log rank P value in the corner and the caption here of P equals 0.011 and our groups have been labeled on the risk table without those cute little colorful circles instead of the default long labels. I love it. It's easy. It's cute. So I want to talk a bit about themes. So there is something called communicate. It was published I think five years ago, 2008, it says right here on the slide. And this was by Morris, Tim Morris, Tom Morris, Tim Morris, I believe. And what they did is they went and surveyed a bunch of statisticians and analysts who do survival analysis regularly and said, here are a bunch of survival figures. Which one do you like? Which one would you like to see? And so they did this survey and they kind of said, okay, well we surveyed a bunch of statisticians and analysts and these are the figures that we kind of all agree are the best. Now, and we wanted to make that very easy to do if you are a communicate convert. I'm not a full communicate convert. I like certain elements of it. Some elements I'm like, I don't feel strongly about. And I'll just stick with like a ggplotdefault for example. So not one size fits all for every, you know, communicate theme, but we did add this theme called theme ggsurfeit communicate. And it does make it very easy to make these graphs that look exactly like the recommendations from that survey of many statisticians. So to get that exact table, what they want is not just the number of risk and the number of events but they also want the number of cumulatively censored patients. So now you're gonna have a bit of a larger risk table. You throw in that theme communicate function we just looked at. And you're going to use a ggplot theme to move the legend into the body of the graph. So that's the part I actually really don't like. Everything else I'm totally fine with. I don't know if the censoring gives a lot more information on top of the number of events. So I don't really feel strongly about that either but more information never killed anyone. So here we are with those three changes to our figure. We have a wonderfully communicate compliant survival analysis figure. So you can see here that there are no more grid lines going up and down guiding you. They're just all horizontal. I think that's perfectly fine. And a little bit of the plot area has been modified with that theme communicate. And again, the legends in the plot area and our risk table has three rows. Risk table, the number at risk, the number of cumulatively censored patients and the number of cumulative events observed. So if you love that, there are other themes in the package as well but I think this is probably the most commonly used one. All right. So for our friends who are in the pharmaceutical industry who are using the C-disk Adam data model or specifically the ADTTE data frames, this is a quick example of what they look like. There's this program column that's kind of, that tells you what the outcome is. So in this case, I'm using this ADTT data set and it says that this is a progression free survival endpoint of, it has a column called of all or and that is our analysis value. So that's the time value. And we have a sensor column CNSR, that is are you censored? Yes or no. So a one means you're censored, a zero means you're not censored or you have the event of interest. And then in this case, TRT01P is our stratifying treatment variable. So these are all highly, highly specified column names in the Adam model. And so you can kind of count on these being your column names. So the most jarring thing here that I find is that the outcome is called sensor and it's programmed in the exact opposite way that you would expect to do a survival analysis where typically you would say, I'm interested in this event. Yes, did you have a recurrence? One, you didn't have a recurrence of zero. They've gone and done the opposite. So it's like a very ripe space to make mistakes. And so to alleviate that concern, we wrote a function called serve sensor. So it's just like the serve function from the survival package, but it just does a quick transformation for you internally. And you can look at that second bullet point there, where time equals a vol and event is one minus sensor. We're doing right censoring and we're doing an origin of zero. So we can make all those assumptions because that's what the Adam data model kind of imposes on us, all right? And also GGSurfit can look for this kind of structure data set and say like, oh, you have a param column along with a vol and sensor. Oh, you must be using the CDISC Adam model. I'm going to use that param column to give you some better labeling in your default labeling in your figure. Of course, you can change it. So by just using this Adam data set ADTTE and the serve sensor, we can very, very easily without having to transform the data ourselves, make a risk of figure, excuse me. And you can see here that everything just works out. It's all Q, it works out. And oh, yes. And then you can see the time, the X axis, it does have a nicer label here from the param column of that data set. So perfection of three survival years rather than the default just would have been like time or something. Okay, so competing risk data. We're coming into the home stretch here. So I know this is a lot of information. Competing risk data is another flavor of survival data. So the most common type of competing risk you're going to encounter while you're doing work. Is that you, so a competing event is something that modifies the risk of the invent of interest that you're actually modeling. And what that commonly means is something's happened so that the chance of your event of interest occurring is now a zero. And that is commonly going to be death from another cause unrelated. So that's what you're gonna be working on. Oh, we have a quick question over here from Ling. Is there option for CI or confidence bands? I'm not quite sure. Anything that, so we're taking the calculations directly from the surfeit object from the survival package. So if you can, whatever transformation or whatever confidence interval calculation that you want, if it's possible in surfeit, it's possible in GG surfeit. I hope that helps. Okay, back to competing risk real quick. We, so in this, so the competing risk we're gonna illustrate here is death from another cause. So we're looking at, you know, recurrence of disease. And if I'm following up someone for a recurrence of their cancer and they end up dying of something totally unrelated to their treatments or their cancer, which happens unfortunately sometimes, the chance that we observe them recurring is now zero. And that's called a competing event. And you can go look this up. There are lots of papers showing that if you don't account for those kinds of changes in the data that you are biasing your results somewhat. And GG surfeit package plays nicely with the tidy comp risk package for doing competing risks analysis. So in tidy comp risk, you use the Q Inc function to get the cumulative incidence estimates. So that very first line is just a vanilla call from the tidy comp risk package. And you pipe that instead of piping it into GG surfeit you pipe it into GG Q Inc. And you tell which of the outcomes you're interested in because we're looking at death from cancer here when the competing event here is also death from other causes. So we're primarily interested in death from cancer. And then after that, everything else is exactly the same. It's all the same. So essentially swap out your GG surfeit call with a GG Q Inc call and you are good to go. So easy peasy I think. A couple of other more advanced customizations that you may need are some figures that are side-by-side. My favorite package to kind of cobble together GG plots is called patchwork. It's really nice, super easy to use. But before you can use patchwork with GG surfeit you need to understand a little bit about how the figures are constructed in the background. Now remember I said that you can do anything you can modify your primary plot in GG surfeit in any way and the risk table will still align. And that is because we delay the construction of the risk table until you've made all of your adjustments to that primary plot. So if you're adding the padding and it's huge if you're squishing this part of expanding that part which is all possible in GG plot we are gonna delay the construction of our risk table to match that, right? So that's how we get it to line up no matter what you've done. And that is done in the print method via a function called GG surfeit build. So when you build your GG surfeit I'm taking that primary plot I'm looking at exactly all the modifications you've made and I am constructing the risk tables in the exact same way to make sure they perfectly align with one another. So you just have to account for that building part before you can use patchwork because otherwise that building will never occur and you won't have what you're looking for. I do have an open issue in patchwork right now to kind of expose one of the intricacies of the package to the users so that we can write methods for it and like S3 methods for example for my class of GG surfeit. So I can do a slight building before we cobble them together with patchwork. The issue has been marked as a feature request and hasn't been closed immediately. It's been open for I think over just over a year now. So hopefully it's a very, very small change but hopefully that will be in some future release of patchwork and we can simplify this process because I'm gonna show you the code now it's not the easiest. So the first set of codes here we're making our GG plot our GG surfeit plot and saving it to the object P and then around line eight we are building that GG surfeit and we're saving it as a new object built P and once you have built P then you can use those patchwork operators. Here we're using the horizontal bar because I wanna put two plots for each other. You can use a slash to stack them. There's a lot of ways you can do this and these are really great. So if this feature does get implemented in the future then you can see on line 10 you would be able to call it just like P vertical bar P. Okay, we have a question from Suman. Did you already indicate that this package is not useful to fit a Cox model? If not, then can a Cox model with splines of a continuous variable with interactions of another variable can be used? Thanks. So Cox models are a bit out of scope because a univariate representation of the Kaplan-Meier estimator is actually quite different from the Cox. If you do go to the package website and there is a vignette called gallery on the website if you scroll to the very, very bottom there is one case where you actually can use GG surfeit with a Cox model and that's because survival surfeit was also written to be able to handle this kind of thing and it's a special type of Cox model called a stratified Cox model. So if you're doing a stratified Cox model you can visualize those stratum with GG surfeit but as far as working with splines and you know all these other things you really need to look into the details of how the surfeit is handling that. Splines when you're kind of doing it adjusted for the years they really need to be very, very careful because you can't just take the average like you typically would with a covariate because if I've done splines for age for example I might have like two, three or four or five or more variables in my Cox model representing that curvy age relationship and what I would need to do there to do an adjusted model would be get the average age or the mean age and then calculate what each spline value would be at that average age rather than just taking the average of those new spline columns. So just be very, very careful whenever you're working with anything adjusted when you have splines. Hope that helps. All right and we're wrapping it up. So why GG surfeit? I think it makes the creation of these very, very common figures super easy. The code is, there's only a handful of functions you need to write to remember and you are ready to publish these figures and I think the defaults have really been thought out quite well and they're very sensible and we also do competing risks. So if there are more questions I'm happy to answer them now. All right, well I'm glad we got some answers during along the way and please if you have questions go to Stack Overflow there's a GG surfeit tag you can add to all of your Stack Overflow questions. I will be notified but there's also a chance that someone else will answer your question before I see it and that would be great. We have one more question. Can we get the slides so that we can use the codes and update as needed? Yeah, can we put the slides into the slides URL into the chat? I don't have it with Ami at this very moment. And then we have another question. Not a question, but can't thank you enough for the TT summary fact. Oh, thank you. It's one of my favorites. Thank you. All right, we'll leave it open until we get that. Let me see if I can grab that. All right, I think I was able to paste it in there so that's the link to the webinars website which has links to the slides which will be updated with a link to the recording in the future. So I think that should have you covered. All right, well thank you everyone for coming and sticking around for an hour about GG surfeit. I hope that the package can help you create beautiful figures, super reproducible and super easy to, I like easy. Thank you everyone.