简体   繁体   中英

R Shiny “non-numeric argument to binary operator” error

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM