I am making a simple Shiny app that inputs a player's name and statistic and then returns the percentile that the player is in for that statistic. I am currently running into an issue where the 'statistic' widget is causing an error (see title).
Here are the packages I am using and a sample of the data:
library(shiny)
library(dplyr)
library(mosaic)
player <- c("John", "Mike", "Devon", "Greg", "Bruce", "Zachary", "Jack", "Graham", "Jordan", "Sandy")
team <- c("A", "B", "A", "B", "A", "B", "A", "B", "A", "B")
wins <- c(1:10)
losses <- c(10:1)
sampledata <- data.frame(player, team, wins, losses)
On the app, there are three widgets: (1) input a player's name, (2) select a stat, and (3) execute the selections.
The output is a single line of text.
Here is the ui.r:
ui <- fluidPage(
titlePanel("Percentile Generator"),
sidebarLayout(
sidebarPanel(
textInput("playerfind",
"Player:",
value = "Devon"),
selectInput("stat1", "Select Statistic:",
choices = list("wins", "losses", "ties"),
selected = "wins"),
actionButton("action", label = "Generate Percentile!")
),
mainPanel(
textOutput("percentmachine")
))
)
The server is a little bit more complicated. Step 1 filters the sample data
and produces a 1x3 dataframe based on the inputs. Step 2 pulls the necessary value out of the matric and stores it. Lastly, step 3 takes the input from step 2 and produces a percentile.
server <- function(input, output) {
step1 <- reactive({sampledata %>%
transmute(player, stat = zscore(input$stat1)) %>%
filter(player == input$playerfind)})
step2 <- reactive({step1()[1,2]})
step3 <- reactive({round(pnorm(step2())*100, digits = 1)})
output$percentmachine <- renderText ({
input$action
isolate(paste(input$playerfind,
"had more",
input$stat1,
"than",
step3(),
"percent of players."))})
}
I believe that the error comes from input$stat1
in step 1. If I replace this input with a specific stat like 'wins', then the shiny app runs fine although the statistic cannot be changed. I have been struggling with this for quite some time so I figured I would ask on here.
Thanks in advance! xD
According to this page , zscore
first argument ( x
) is a numeric vector.
input$stat1
is character.
You are feeding a character
value into a function that takes numeric
.
I'll simulate outside of a shiny/reactive environment.
input <- list(playerfind="Devon", stat1="wins")
# I don't have mosaic installed
zscore <- function( x, na.rm=getOption("na.rm", FALSE) ) ( x - mean(x, na.rm=na.rm)) / sd(x, na.rm=na.rm)
sampledata %>%
transmute(player, stat = zscore(input$stat1))
# Warning in mean.default(x, na.rm = na.rm) :
# argument is not numeric or logical: returning NA
# Error in x - mean(x, na.rm = na.rm) (from #1) :
# non-numeric argument to binary operator
One can to fix this with a trick using get
:
sampledata %>%
transmute(player, stat = zscore(get(input$stat1)))
# player stat
# 1 John -1.4863011
# 2 Mike -1.1560120
# 3 Devon -0.8257228
# 4 Greg -0.4954337
# 5 Bruce -0.1651446
# 6 Zachary 0.1651446
# 7 Jack 0.4954337
# 8 Graham 0.8257228
# 9 Jordan 1.1560120
# 10 Sandy 1.4863011
### which is effectively this
zscore(sampledata$wins)
# [1] -1.4863011 -1.1560120 -0.8257228 -0.4954337 -0.1651446 0.1651446
# [7] 0.4954337 0.8257228 1.1560120 1.4863011
(and then filter
as needed).
Another way to fix this is perhaps overkill, but in case it provides insight into other actions in your project, we can reshape the data from wide to long. Since we're already using dplyr
, I'll include tidyr
:
library(tidyr)
### this is just a demo of reshaping from wide to long
sampledata %>%
pivot_longer(c(-player, -team), names_to = "winlose", values_to = "val")
# # A tibble: 20 x 4
# player team winlose val
# <fct> <fct> <chr> <int>
# 1 John A wins 1
# 2 John A losses 10
# 3 Mike B wins 2
# 4 Mike B losses 9
# 5 Devon A wins 3
# 6 Devon A losses 8
# 7 Greg B wins 4
# 8 Greg B losses 7
# 9 Bruce A wins 5
# 10 Bruce A losses 6
# 11 Zachary B wins 6
# 12 Zachary B losses 5
# 13 Jack A wins 7
# 14 Jack A losses 4
# 15 Graham B wins 8
# 16 Graham B losses 3
# 17 Jordan A wins 9
# 18 Jordan A losses 2
# 19 Sandy B wins 10
# 20 Sandy B losses 1
### this is the actual work
sampledata %>%
pivot_longer(c(-player, -team), names_to = "winlose", values_to = "val") %>%
filter(winlose == input$stat1) %>%
mutate(z = zscore(val))
# # A tibble: 10 x 5
# player team winlose val z
# <fct> <fct> <chr> <int> <dbl>
# 1 John A wins 1 -1.49
# 2 Mike B wins 2 -1.16
# 3 Devon A wins 3 -0.826
# 4 Greg B wins 4 -0.495
# 5 Bruce A wins 5 -0.165
# 6 Zachary B wins 6 0.165
# 7 Jack A wins 7 0.495
# 8 Graham B wins 8 0.826
# 9 Jordan A wins 9 1.16
# 10 Sandy B wins 10 1.49
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.