I want to get the following layout.
In my actual plots, the two plots in the third column are same x-axis and thus I
exhibit them in one column.
The following example Shiny code has the three histograms with one column.
So, we cannot observe how the most lowest histogram changes according to the bins. Thus I want to get the above layout.
Example Shiny Code
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot1"),
plotOutput("distPlot2"),
plotOutput("distPlot3")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$distPlot1 <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
output$distPlot2 <- renderPlot({
# generate bins based on input$bins from ui.R
y <- faithful[, 2]
bins <- seq(min(y), max(y), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(y, breaks = bins, col = 'darkgray', border = 'white')
})
output$distPlot3 <- renderPlot({
# generate bins based on input$bins from ui.R
z <- faithful[, 2]
bins <- seq(min(z), max(z), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(z, breaks = bins, col = 'darkgray', border = 'white')
})
}
# Run the application
shinyApp(ui = ui, server = server)
Please let me know any idea.
Edit for comment
I understand your idea. I do not use ggplot as follows;
x <- c(1, 2, 3, 4, 5)
y1 <- c(1, 1, 2, 3, 1)
y2 <- c(2, 2, 1, 2, 4)
y3 <- c(4, 3, 2, 1, 2)
split.screen(figs = c(1, 2))
split.screen(figs = c(2, 1), screen = 2)
screen(1)
plot(x, y1, type = "l")
screen(3)
plot(x, y2, type = "l")
screen(4)
plot(x, y3, type = "l")
The result is as follows;
I would use ggplot2 and gridExtra to arrange the plots.
Here is the final output I got:
Screenshot
The main plots were done using grid.arrange to combine them together, and ggplot2 gives you more ability to control each of the subplots, named plot1, plot2, and plot3 in the codes, and plot2 and plot3 formed the 3rd column.
Since your 3rd column has different x-axis, I added a second bin width to control them together. And, to make the program a bit more dynamic, I use renderUI and uiOutput to push the data information from the server back to ui to generate the two sliderInputs.
Codes:
library(ggplot2)
library(grid)
library(gridExtra)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
uiOutput("bins1"),
uiOutput("bins2")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("ggplot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
## Your Data and give colnames for ggplot
x <- as.data.frame(faithful[, 2])
y <- as.data.frame(faithful[, 1])
z <- as.data.frame(faithful[, 1])
colnames(x) <- "Count"
colnames(y) <- "Count"
colnames(z) <- "Count"
## Set bin size 1 and 2
binWidth1 <- c(max(x))
binWidth2 <- c(max(y))
output$bins1 <- renderUI({
sliderInput("bins1",
h3("Bin width #1 "),
min = 1,
max = max(x),
value = (1 + max(x))/10)
})
output$bins2 <- renderUI({
sliderInput("bins2",
h3("Bin width #2 "),
min = 1,
max = max(y),
value = (1 +max(y))/10)
})
output$ggplot <- renderPlot({
# bins <- seq(min(x), max(x), length.out = input$bins + 1)
plot1 <- ggplot(x, aes(x = Count)) +
geom_histogram(binwidth = input$bins1, fill = "black", col = "grey")
plot2 <- ggplot(y, aes(x = Count)) +
geom_histogram(binwidth = input$bins2, fill = "black", col = "grey")
plot3 <- ggplot(z, aes(x = Count)) +
geom_histogram(binwidth = input$bins2, fill = "black", col = "grey")
grid.arrange(grid.arrange(plot1), grid.arrange(plot2, plot3, ncol = 1), ncol = 2, widths = c(2, 1))
})
}
# Run the application
shinyApp(ui = ui, server = server)
Related
I have made a pbiviz custom visual using developer tools of Normal distribution curve over a Histogram plot with R - ggplot2 and plotly libraries in a pbiviz.package
The visual works fine. Now I want to add interactivity of the Histogram with other Power BI visuals.
i.e. If user clicks on a bar of the Histogram, it should filter out a Table on my PBI report with rows relevant to the histogram bar data.
Considering the limitations of using R script with Power BI, I do not know if it is possible with my current visual as I am new to scripting.
Is there a better way (Typescript, JS, Python, etc.) other than what I have done to make an Interactive Histogram & Distribution Curve in Power BI?
This is the R script along with sample data and Visual Image
Histogram represents the projects falling in different durations
There are two bell curves - One for closed projects and Other for Active Projects
source('./r_files/flatten_HTML.r')
############### Library Declarations ###############
libraryRequireInstall("ggplot2");
libraryRequireInstall("plotly");
libraryRequireInstall("tidyverse");
libraryRequireInstall("scales");
libraryRequireInstall("htmlwidgets");
library(ggplot2)
library(tidyverse)
library(scales)
library(plotly)
theme_set(theme_bw())
##### Making DataSet for All Selected Projects #####
Duration <- dataset$Duration
Status <- (rep(dataset$ProjectStatus))
da <- data.frame(Duration,Status)
lenx <- length(Duration)
meanall <- mean(da$Duration)
sdx <- sd(da$Duration)
binwidth <- 30
font_label <- list(family = "Segoe UI", size = 21, colour = "black")
hovlabel <- list(bordercolor = "black", font = font_label)
#Filtering Out Closed Projects from Dataset
#Creating Data Frame for Closed Projects
closedproj <- dataset %>%
select(Duration,ProjectStatus) %>%
filter(ProjectStatus == "Closed")
closed <- closedproj$Duration
df <- data.frame(closed)
xclosed <- closedproj$
df2 <- data.frame(xclosed)
lenc <- length(xclosed)
mean_closed <- mean(df2$xclosed)
sdc <- sd(df2$xclosed)
a <-
(ggplot(da,aes(x=Duration, fill = Status, text = paste("Duration: ",x,"-", x + binwidth,"<br />Project Count", ..count..)))+
#Histogram
geom_histogram(aes(y=..count..),alpha=0.5, position='identity',binwidth = binwidth)+
# #Distribution Curve
annotate(
geom = "line",
x = da$Duration,
y = dnorm(da$Duration, mean = meanall, sd = sdx) * lenx * binwidth,
width = 3,
color = "red"
) +
annotate(
geom = "line",
x = df2$xclosed,
y = dnorm(df2$xclosed, mean = mean_closed, sd = sdc)* lenc * binwidth,
width = 3,
color = "blue"
) +
labs(
x = "Project Duration (Days)",
y = "Project_Count",
fill = "Project Status")+
#Mean
geom_vline(aes(xintercept=meanall),color="red",linetype="dashed",size = 0.8,label=paste("Mean :",round(meanall,0)))+
geom_vline(aes(xintercept=mean_closed),color="blue",linetype="dashed",size = 0.8,label=paste("Mean (Closed):",round(mean_closed,0)))+
# 1 Sigma
geom_vline(aes(xintercept = (meanall + sdx)), color = "red", size = 1, linetype = "dashed") +
geom_vline(aes(xintercept = (meanall - sdx)), color = "red", size = 1, linetype = "dashed")+
geom_vline(aes(xintercept = (mean_closed + sdc)), color = "blue", size = 1, linetype = "dashed") +
geom_vline(aes(xintercept = (mean_closed - sdc)), color = "blue", size = 1, linetype = "dashed")+
# Theme
theme(
plot.background = element_rect(fill = "transparent"),
legend.background = element_rect(fill = "lightgray"),
axis.title.x = element_text(colour = "Black",size = 18,face = "bold"),
axis.title.y = element_text(colour = "Black",size = 18,face = "bold"),
axis.text.x = element_text(colour = "Black",size = 15),
axis.text.y = element_text(colour = "Black",size = 15),
panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
scale_x_continuous(labels = comma,
breaks = seq(0, max(Duration),50)) +
scale_y_continuous(labels = comma,
breaks = seq(0,max(Duration),10)))
############# Create and save widget ###############
p = ggplotly(a, tooltip = c("text")) %>%
style(hoverlabel = hovlabel) %>%
layout(legend = list(
orientation = "h",
x = 0,
y = 1.13,
title = list(text = "Project Status",font = list(family = "Segoe UI", size = 23)),
font = font_label
),
yaxis = list(title = list(standoff = 25L)),
xaxis = list(title = list(standoff = 25L)),
annotations = list(showarrow=FALSE,align = "left",valign = "top",x = 0.95, xref = "paper",yref = "paper",y = 0.955,
font = list(family = "Segoe UI", size = 22, color = "#cc0000"),
text = paste("Max Duration: ", comma(round(max(da$Duration),0)),
"<br>Mean (Closed): ", comma(round(mean_closed,0)),
"<br>Mean (All) : ", comma(round(meanall,0))))
) %>%
config(modeBarButtonsToRemove = c("select2d","hoverClosestCartesian", "lasso2d","hoverCompareCartesian","toggleSpikelines"), displaylogo = FALSE);
internalSaveWidget(p, 'out.html');
}
####################################################
################ Reduce paddings ###################
ReadFullFileReplaceString('out.html', 'out.html', ',"padding":[0-5]*,', ',"padding":0,')
What I expect is -- If user clicks on a bar of the Histogram, it should reflect on a Table visual on my PBI report with rows relevant to the histogram bar data.
Any help will be highly appreciated !
Regards
I am trying to create a table using rhandsontable with several rows of merged cells (different cells in each row).
I am trying to achieve merging of the indicated cells in the screenshot below ...
I am able to successfully merge the first set of cells (row 11) but subsequent merges using a "list of lists" to specify the cells doesn't work. I have tried every permutation of the "list of lists" syntax that I can think of;
a reprex of the example is here ...
library(shiny)
library(rhandsontable)
## Create the data set
DF = data.frame((Cycle = 1:13),
`A` = as.numeric(""),
`B` = as.numeric(""),
`C` = as.numeric(""),
`D` = as.numeric(""))
DF[11,1] = "Total"
DF[12,1] = ""
DF[13,1] = "Loss"
server <- shinyServer(function(input, output, session) {
output$hotTable <- renderRHandsontable({rhandsontable(DF,
width = 1500, height = 350, rowHeaders = FALSE) %>%
hot_cols(colWidths = c(100, 150, 150, 150, 150)) %>%
hot_col(c(1,3:5), readOnly = TRUE) %>%
hot_col(col = c(1:5), halign = "htCenter") %>%
hot_col(col = c(2:4), format = "0.0000") %>%
hot_col(col = 5, format = 0000) %>%
hot_table(mergeCells = list(list(row = 10, col = 2, rowspan = 1, colspan = 3),
list(row = 11, col = 1, rowspan = 1, colspan = 5),
list(row = 12, col = 3, rowspan = 1, colspan = 3)))})
})
ui <- basicPage(mainPanel(rHandsontableOutput("hotTable")))
shinyApp(ui, server)
I think you should change some parameters as follow:
mergeCells = list(list(row = 10, col = 2, rowspan = 1, colspan = 3),
list(row = 11, col = 0, rowspan = 1, colspan = 5),
list(row = 12, col = 2, rowspan = 1, colspan = 3))
so your desired rhandsontable would be produced as you want:
#The code below works fine in my scripts but not in R markdown.
library(tidyverse)
library(scales)
age <- kaggle_2020_Survey %>%
transmute(Q1 = as.factor(Q1)) %>%
filter(!is.na(Q1)) %>%
count(Q1) %>%
mutate(perc = n/sum(n)*100)
ggplot(age, aes(x = Q1, y = n)) + geom_col(fill = "darkblue", alpha =.7) +
geom_text (aes(x = Q1, y = n, label = paste0(round(perc,1), "%"),hjust = -.3), size = 3)
+
coord_flip() + labs(title = "Age of participants", x = "Percent", y = "Number",
subtitle = "Highest age group: 22-24") +
theme_classic()
#This is the error I am getting:
enter image description here
It could be that the object is in your environment but you forgot to include something like
library(tidyverse)
kaggle_2020_Survey <- read_csv("kaggle_2020_Survey.csv")
where you load in the data. When you knit a rmarkdown file it starts a new session each time so if the data isn't called in before you start doing stuff then it will throw that error
This answer goes into other solutions.
I am creating a Shiny app where I would like to have the default of a numericInput be dependent on another default to a previously defined numericInput.
e.g.,
Here I would like the numericInput elements of (2) to be the reciprocal of (1), without having to specify values for value,min,max, and step beforehand:
(1) numericInput("obs1", "Label1", value = 10, min = 10, max = 20, step = 1)
(2) numericInput("obs2", "Label2", value = 1/10, min = 1/10, max = 1/20, step = 1)
Above (1) is the previously-defined numericInput.
Is there a simple way to do this?
If you want an input object to have dynamic parameters you need to use uiOutput, so that you can generate them in runtime (in server.R).
Example: In the first column you can set min, max and value. Modifying any of them renders obs1 and obs2 with new parameter values.
library(shiny)
ui <- fluidPage(
column(6,
tags$h2("Set parameters"),
numericInput("value", "Value", value = 20, min = 10, max = 60, step = 10),
numericInput("min", "Min", value = 10, min = 0, max = 30, step = 10),
numericInput("max", "Max", value = 40, min = 40, max = 60, step = 10)
),
column(6,
uiOutput("ui")
)
)
server <- function(input, output, session) {
output$ui <- renderUI( {
tagList(
tags$h2("Numeric inputs that depend on reactive data"),
numericInput("obs1", "Label1", value = input$value, min = input$min, max = input$max, step = 1),
numericInput("obs2", "Label2", value = input$value + 5, min = input$min - 5, max = input$max + 5, step = 1)
)
})
}
shinyApp(ui, server)
Please note that you need to wrap elements in tagList, when you want to pass more than one input element to renderUI.
In the Shiny dashboard tutorial of the Wikimedia foundation a screenshot is shown with a kind of horizontal stacked bar (the one with red, green, and blue "Full-text...OpenSearch..Prefix):
I have been searching everywhere, but I cannot find out how to create a bar like this. Can anyone point me in the right direction?
This is not a great answer, but it works. Requires learning some ggplot2 if you want to tweak it, and I tried to get rid of the border around the edges but it isn't gone completely. Still, the basic idea is here.
library(ggplot2)
mydf <- data.frame(labels = c('This', 'that', 'the other'),
percents = c(0.31, 0.15, 0.54))
mydf$pos <- pmax(0, cumsum(mydf$percents) - (0.5 * mydf$percents))
p <- ggplot(mydf, aes(x = NA, y = percents)) +
geom_bar(stat = 'identity', aes(fill = percents)) +
geom_text(color = 'white', aes(label = labels, y = pos)) +
coord_flip() +
guides(fill = FALSE) +
scale_x_discrete(expand = c(0, 0)) +
scale_y_discrete(expand = c(0, 0)) +
theme_void()
png('this_plot.png', width = 800, height = 30)
p
dev.off()