Generating a Call Graph in R

Call function to generate the value but without plotting the graph

You can provide an argument that allows users to choose whether to plot or not, FALSE by default below. Then just wrap the call to plot() with an if statement that executes if the argument is TRUE.

library(dplyr)
library(tidyverse)
library(lubridate)

Test <- structure(
list(date1= c("2021-06-28","2021-06-28"),
date2 = c("2021-07-01","2021-07-01"),
Category = c("FDE","ABC"),
Week= c("Friday","Monday"),
DR1 = c(14,11),
DR01 = c(14,12), DR02= c(14,12),DR03= c(19,15),
DR04 = c(15,14),DR05 = c(15,14),
DR06 = c(12,14)),
class = "data.frame", row.names = c(NA, -2L))

f1 <- function(df1, dmda, CategoryChosse, plot = FALSE) {

x<-df1 %>% select(starts_with("DR0"))

x<-cbind(df1, setNames(df1$DR1 - x, paste0(names(x), "_PV")))
PV<-select(x, date2,Week, Category, DR1, ends_with("PV"))

med<-PV %>%
group_by(Category,Week) %>%
summarize(across(ends_with("PV"), median),.groups = 'drop')

SPV<-df1%>%
inner_join(med, by = c('Category', 'Week')) %>%
mutate(across(matches("^DR0\\d+$"), ~.x +
get(paste0(cur_column(), '_PV')),
.names = '{col}_{col}_PV')) %>%
select(date1:Category, DR01_DR01_PV:last_col())

SPV<-data.frame(SPV)

mat1 <- df1 %>%
filter(date2 == dmda, Category == CategoryChosse) %>%
select(starts_with("DR0")) %>%
pivot_longer(cols = everything()) %>%
arrange(desc(row_number())) %>%
mutate(cs = cumsum(value)) %>%
filter(cs == 0) %>%
pull(name)

(dropnames <- paste0(mat1,"_",mat1, "_PV"))

datas<-SPV %>%
filter(date2 == ymd(dmda)) %>%
group_by(Category) %>%
summarize(across(starts_with("DR0"), sum),.groups = 'drop') %>%
pivot_longer(cols= -Category, names_pattern = "DR0(.+)", values_to = "val") %>%
mutate(name = readr::parse_number(name))
colnames(datas)[-1]<-c("Days","Numbers")

if(as.Date(dmda) < min(as.Date(df1$date1))){
datas <- datas %>%
group_by(Category) %>%
slice(1:max(Days)+1) %>%
ungroup
}else{
datas <- datas %>%
group_by(Category) %>%
slice((as.Date(dmda) - min(as.Date(df1$date1) [
df1$Category == first(Category)])):max(Days)+1) %>%
ungroup
}

model <- nls(Numbers ~ b1*Days^2+b2,start = list(b1 = 0,b2 = 0),data = datas, algorithm = "port")
coef_val<-coef(model)[2]

if(plot){
new.data <- data.frame(Days = with(datas, seq(min(Days),max(Days),len = 45)))
new.data <- rbind(0, new.data)

plot(Numbers ~ Days, xlim= c(0,45), ylim= c(0,30),
xaxs='i',data = datas,main = paste0(dmda, "-", CategoryChosse))
lines(new.data$Days,predict(model,newdata = new.data),lwd=2)
points(0, coef_val, col="red",pch=19,cex = 2,xpd=TRUE)
}

return(coef_val)
}

Demonstrating it in use:


f1(Test, "2021-07-01", "ABC")
f1(Test, "2021-07-01", "ABC", plot = TRUE)

Create a call graph for a specific function using Doxygen

This is a bit depending on your version of doxygen.
But besides the configuration settings (always needed HAVE_DOT=YES):

  • CALL_GRAPH
  • CALLER_GRAPH

there are the commands (see https://www.doxygen.nl/manual/commands.html):

  • \callgraph
  • \callergraph
  • \hidecallgraph
  • hidecallergraph

with these commands it should be possible to create the required graphs.

Upon request:

The doxygen configuration file

HAVE_DOT=YES

The source code file

/// \file

/// \brief the first fie
/// \details the details of the first fie
/// \callgraph
void fie1(void)
{
fie2();
};

/// \brief the second fie
/// \details the details of the second fie
void fie2(void);

Calling a graph from another sheet in R

You can make a function that takes arguments for the plot that you make like the data and plot title and then passes these arguments to your code that creates the plot. For example, say the only thing that changes is x and the plot title, you can define a function that takes those arguments and then uses them in the code to make the plot. Then you save this in a separate script and call the script using source() in your shiny app.

plots.R

plot_data <- function(x, y=NULL, plot.title){

if(is.null(y)) {
y <- seq(from = 1, by = 1, length.out = length(x))
}

plot(x, y, main = plot.title)

}

Load the function into your global environment using source('plots.R'), make sure plots.R is saved in the same location as your shiny app.

library(shiny)

source("plots.R")

ui <- fluidPage(
mainPanel(
selectInput("input1","Select an option",choices = c("First","Second")),
plotOutput("plot1"),
plotOutput("plot2")
)
)

server <- function(input, output, session) {
output$plot1 = renderPlot({
if(input$input1=="First"){
##This is where I'd like to call the code for the graph from another sheet.
plot_data(1, plot.title = input$input1)
}
if(input$input1=="Second"){
##Again, this is where I'd like to code for the graph from another sheet.
plot_data(2, plot.title = input$input1)
}
})

output$plot2 = renderPlot({
if(input$input1=="First"){
##This is where I'd like to call the code for the graph from another sheet.

plot_data(1*rnorm(1,10,2),plot.title = input$input1)

}
if(input$input1=="Second"){
##Again, this is where I'd like to code for the graph from another sheet.
plot_data(2*rnorm(1,50,2),plot.title = input$input1)
}
})

}

shinyApp(ui, server)

Of course this doesn't look like much of a difference, but with complex plots that span multiple lines, turning your plot code into a function will turn multiple lines into just one.



Related Topics



Leave a reply



Submit