[英]R Shiny “non-numeric argument to binary operator” error
我正在制作一个简单的 Shiny 应用程序,该应用程序输入玩家的姓名和统计数据,然后返回玩家在该统计数据中的百分位数。 我目前遇到“统计”小部件导致错误的问题(见标题)。
以下是我正在使用的包和数据示例:
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)
在应用程序上,有三个小部件:(1) 输入玩家姓名,(2) select 统计数据,以及 (3) 执行选择。
output 是单行文本。
这是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")
))
)
服务器稍微复杂一些。 第 1 步过滤sample data
并根据输入生成 1x3 dataframe。 第 2 步从矩阵中提取必要的值并将其存储。 最后,第 3 步从第 2 步获取输入并生成一个百分位数。
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."))})
}
我相信错误来自步骤 1 中的input$stat1
。如果我将此输入替换为特定的统计信息,例如“wins”,则 shiny 应用程序运行良好,尽管无法更改统计信息。 我已经为此苦苦挣扎了一段时间,所以我想我会在这里问。
提前致谢! xD
根据this page , zscore
第一个参数( x
)是一个数字向量。
input$stat1
是字符。
您正在将一个character
值输入一个采用numeric
的 function 。
我将在闪亮/反应性环境之外进行模拟。
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
可以使用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
(然后根据需要filter
)。
解决此问题的另一种方法可能是矫枉过正,但如果它提供对您项目中其他操作的洞察力,我们可以将数据从宽调整为长。 由于我们已经在使用dplyr
,我将包括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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.