Reputation: 13
I have built a shiny app in which my inputs only recognize numeric values. For example, in the text box I insert 2^7 and it doesn´t perform the procedure in my function from the R code. On the other hand if I insert 128 it does perform the procedure.
library(shiny)
library(shinythemes)
library(shinydashboard)
library(stringr)
library(ggplot2)
ui = navbarPage(
theme = shinytheme("superhero"),
title = "Generador de Numeros Aleatorios",
tabPanel(title = h5("Generadores"),
sidebarPanel(
selectInput("metodo", "Selecciona el m?todo",
selected= "Multiplicativo",
choices = c("Multiplicativo","Lineal","SimuladorR")
),
textInput("z0","Ingresa una semilla:",value = 3),
texticInput("n","Ingresa 'n':",value=10),
textInput("a","Ingresa 'a':",value=2),
textInput("m","Ingresa 'm':", value=15),
textInput("c","Ingresa 'c':",value=10),
actionButton("generador", label = "Generar"),
br(),
radioButtons("type", "Formato de descarga:",
choices=c("Excel(CVS)", "Text(TSV)"),selected = "Excel(CVS)", inline=T),
helpText("Click en el boton de Exportar para descragar los datos."),
downloadButton('downloaddata','Exportar')
#downloadButton("exportador", label = "Exportar")
#actionButton("exportador", label = "Exportar"),
#br(),
#helpText("Click en el boton de Exportar para descargar los datos"),
), #Cierra sidebarPanel
mainPanel(
h5("Valores Generados:"),
plotOutput("grafica"),
tableOutput("tablaValores")
) #Cierra mainPanel
),
server = function(input, output,session){
## Generador Multiplicativo
Congruencial.Multiplicativo = function(z0,a,m,n){
z<-c()
u<-c()
z[1]<-z0
u[1]<-z[1]/m
if(n>1){
for (i in 1:n+1) {
z[i]<-(a*z[i-1]) - floor((a*z[i-1])/m)*m
}
for(i in 1:n+1){
u[i]<-z[i]/m
}
}
return(u[-1])
}
## Generador Lineal
Congruencial.Lineal<-function(z0,m,a,c,n){
z=c()
k=c()
u=c()
z[1]=z0
k[1]=floor(((a*z[1])+c)/m)
for(i in seq(2,n+1,by=1)){
z[i]=((a*z[i-1])+c)-(m*k[i-1])
k[i]=floor(((a*z[i])+c)/m)
u[i]=z[i]/m
}
return(u[-1])
}
## Generador de R
Simulador.R = function(n){
r<-runif(n=n,min=0,max=1)
return(r)
}
### Ahora para mostrar los valores guardados:
observeEvent(input$generador, {
output$grafica = renderPlot ({
datos = valores()
datos = as.data.frame(datos)
ggplot(datos)+geom_histogram(aes(x=datos,y=..density..),
breaks=seq(0, 1, .01),closed="left",
color="white", fill="orange")+
labs(title="Funcion de Densidad",
x=" x ",
y = "Densidad"
)+theme_bw()+
scale_x_continuous(breaks =seq(0, 1, 0.1))+
scale_y_continuous(breaks =seq(0, 1, 0.1))+
stat_function(fun=dunif,xlim=c(-.5,1.5),size=1,color="red",
args =list(min=0, max=1) )
})
valores = reactive({ switch (input$metodo,
Multiplicativo =
Congruencial.Multiplicativo(input$z0,input$a,input$m,input$n),
Lineal = Congruencial.Lineal(input$z0,input$m,input$a,input$c,input$n),
SimuladorR = Simulador.R(input$n) )}) #Cierra valores
numord = valores() #Llamamos los valores aleatorios generados
mostrar = as.data.frame(cbind(seq(1,input$n,by=1),numord))
colnames(mostrar)=c("i", "u")
output$tablaValores = renderTable(mostrar)
}) #Cierra observeEvent
Now this is part of the code in which I need the text input to be recognized as numeric so that the app can work. The values I need the app to read as a string and turn them into numeric are z0, n, m, c. I have tried to put them into the observe event and neither they work.
The app creates a series of semirandom values with generators, that need some entry values which are specified in the paragraph above.
Upvotes: 0
Views: 1338
Reputation: 30474
Here is a demo that might be helpful. You can input a character string, and then use eval(parse(text = ...
to evaluate the expression.
library(shiny)
ui <- fluidPage(
textInput("ti_math", "Enter formula:"),
textOutput("to_result")
)
server <- function(input, output, session) {
output$to_result <- renderText({
eval(parse(text = input$ti_math))
})
}
shinyApp(ui, server)
Disclaimer: while this should work, the assumption is that the app will be running locally. Using eval
on user input can be a security risk. See this post for more information.
Edit: Thank you for providing additional code. I was not able to reproduce completely (missing valores()
) but I think I can make a couple suggestions.
For z0, n, m, c, you can access the inputs through input$z0
, etc.
Try this:
observeEvent(input$generador, {
z0 = eval(parse(text = input$z0))
print(z0)
})
You should see in your console, that if you provide something like 3^4
for z0
it should show 81 and be numeric.
You could do the same for n, m, c - I'm guessing you might be accessing these variables in valores()
or other reactive
expression.
I also noticed you have output$grafica
and output$tablaValores
inside of your observeEvent
- I would recommend moving them out of observeEvent
. One strategy is to use something <- eventReactive(input$generador, {...
and then call something()
from plot and table outputs.
Edit: Thank you for providing valores()
. I can now provide something more reproducible.
I included eval(parse(text = input$...))
for z0, n, a, m, c. This is inside valores()
so that all functions using these values for calculations will be evaluated for mathematical symbols first.
Note that I moved the renderTable
and renderPlot
from observeEvent
, and changed observeEvent
to eventReactive
which will be responsive to the action button.
I also changed ui
and server
to separate components, and then call shinyApp
in the end (just a preference).
This does provide a table and plot when button pressed. Please let me know if this is closer.
library(shiny)
library(shinythemes)
library(shinydashboard)
library(stringr)
library(ggplot2)
ui = navbarPage(
theme = shinytheme("superhero"),
title = "Generador de Numeros Aleatorios",
tabPanel(title = h5("Generadores"),
sidebarPanel(
selectInput("metodo", "Selecciona el m?todo",
selected= "Multiplicativo",
choices = c("Multiplicativo","Lineal","SimuladorR")
),
textInput("z0","Ingresa una semilla:",value = 3),
textInput("n","Ingresa 'n':",value=10),
textInput("a","Ingresa 'a':",value=2),
textInput("m","Ingresa 'm':", value=15),
textInput("c","Ingresa 'c':",value=10),
actionButton("generador", label = "Generar"),
br(),
radioButtons("type", "Formato de descarga:",
choices=c("Excel(CVS)", "Text(TSV)"),selected = "Excel(CVS)", inline=T),
helpText("Click en el boton de Exportar para descragar los datos."),
downloadButton('downloaddata','Exportar')
#downloadButton("exportador", label = "Exportar")
#actionButton("exportador", label = "Exportar"),
#br(),
#helpText("Click en el boton de Exportar para descargar los datos"),
), #Cierra sidebarPanel
mainPanel(
h5("Valores Generados:"),
plotOutput("grafica"),
tableOutput("tablaValores")
) #Cierra mainPanel
)
)
server = function(input, output,session){
## Generador Multiplicativo
Congruencial.Multiplicativo = function(z0,a,m,n){
z<-c()
u<-c()
z[1]<-z0
u[1]<-z[1]/m
if(n>1){
for (i in 1:n+1) {
z[i]<-(a*z[i-1]) - floor((a*z[i-1])/m)*m
}
for(i in 1:n+1){
u[i]<-z[i]/m
}
}
return(u[-1])
}
## Generador Lineal
Congruencial.Lineal<-function(z0,m,a,c,n){
z=c()
k=c()
u=c()
z[1]=z0
k[1]=floor(((a*z[1])+c)/m)
for(i in seq(2,n+1,by=1)){
z[i]=((a*z[i-1])+c)-(m*k[i-1])
k[i]=floor(((a*z[i])+c)/m)
u[i]=z[i]/m
}
return(u[-1])
}
## Generador de R
Simulador.R = function(n){
r<-runif(n=n,min=0,max=1)
return(r)
}
valores = eventReactive(input$generador, {
z0 = eval(parse(text = input$z0))
a = eval(parse(text = input$a))
m = eval(parse(text = input$m))
c = eval(parse(text = input$c))
n = eval(parse(text = input$n))
switch (input$metodo,
Multiplicativo = Congruencial.Multiplicativo(z0,a,m,n),
Lineal = Congruencial.Lineal(z0,m,a,c,n),
SimuladorR = Simulador.R(n)
)
}) #Cierra valores
output$tablaValores = renderTable({
numord = valores() #Llamamos los valores aleatorios generados
mostrar = as.data.frame(cbind(seq(1,input$n,by=1),numord))
colnames(mostrar)=c("i", "u")
mostrar
})
output$grafica = renderPlot ({
datos = valores()
datos = as.data.frame(datos)
ggplot(datos)+geom_histogram(aes(x=datos,y=..density..),
breaks=seq(0, 1, .01),closed="left",
color="white", fill="orange")+
labs(title="Funcion de Densidad",
x=" x ",
y = "Densidad"
)+theme_bw()+
scale_x_continuous(breaks =seq(0, 1, 0.1))+
scale_y_continuous(breaks =seq(0, 1, 0.1))+
stat_function(fun=dunif,xlim=c(-.5,1.5),size=1,color="red",
args =list(min=0, max=1) )
})
}
shinyApp(ui, server)
Upvotes: 1
Reputation: 84529
eval(text = parse(......))
works fine but it is dangerous. You can turn any string to an evaluated R command with this way, for example a command which deletes some files...
Since the strings you enter are mathematical expressions, you can use the Ryacas
package to evaluate them. Ryacas
will fail if the string is not a mathematical expression.
library(Ryacas)
.......
valores = eventReactive(input$generador, {
z0 = as.numeric(yac_str(sprintf("N(%s)", input$z0)))
a = as.numeric(yac_str(sprintf("N(%s)", input$a)))
m = as.numeric(yac_str(sprintf("N(%s)", input$m)))
c = as.numeric(yac_str(sprintf("N(%s)", input$c)))
n = as.numeric(yac_str(sprintf("N(%s)", input$n)))
......
Upvotes: 2