如何在Shiny服务器函数内定义复用函数判断冠词a/an的使用
解决方案:复用判断"a"/"an"的函数
当然可以!你完全可以在Shiny的server函数内部定义一个可复用的小函数,把重复的元音判断逻辑抽离出来,让代码更简洁优雅。
步骤1:定义复用函数
在server函数的开头(或者任何你觉得合适的位置),添加一个名为get_indefinite_article的函数,它接收一个标签字符串,根据首字母是否为元音返回"a"或"an":
server <- function(input, output) { # 定义复用的不定冠词判断函数 get_indefinite_article <- function(label) { # 转成小写避免大小写问题(比如标签开头是大写元音的情况) first_char <- tolower(substr(label, 1, 1)) if (first_char %in% c("a", "e", "i", "o", "u")) { return("an") } else { return("a") } } # 剩下的server代码... }
步骤2:简化stringX和stringY的逻辑
现在你可以把原来stringX和stringY里重复的判断逻辑替换成调用这个函数,让代码变得更简洁:
stringX <- reactive({ if (inputX() > -999) { article <- get_indefinite_article(labelX()) paste("You have selected", article, labelX(), "of", inputX()) } else { "" } }) stringY <- reactive({ if (inputY() > -999) { article <- get_indefinite_article(labelY()) paste("and", article, labelY(), "of", inputY()) } else { "" } })
完整修改后的server代码
这里是整合后的完整server部分,你可以直接替换原来的代码:
server <- function(input, output) { # 定义复用的不定冠词判断函数 get_indefinite_article <- function(label) { first_char <- tolower(substr(label, 1, 1)) if (first_char %in% c("a", "e", "i", "o", "u")) { return("an") } else { return("a") } } output$plot1 <- renderPlot({ ggplot(myData, aes(weight, attack)) + geom_point() }) ## Extract some values when plot is clicked inputX <- reactive({ if (is.null(input$plot_click$x)) { -999 } else { round(input$plot_click$x, 0) } }) inputY <- reactive({ if (is.null(input$plot_click$y)) { -999 } else { round(input$plot_click$y, 0) } }) labelX <- eventReactive(input$plot_click, { input$plot_click$mapping$x }) labelY <- eventReactive(input$plot_click,{ input$plot_click$mapping$y }) ## count the number of points that have a higher x and y. mySubset <- eventReactive(input$plot_click, { subset(myData, .data[[labelX()]] > inputX() & .data[[labelY()]] > inputY()) }) ## Create relevant strings out of the inputX and inputY values. stringX <- reactive({ if (inputX() > -999) { article <- get_indefinite_article(labelX()) paste("You have selected", article, labelX(), "of", inputX()) } else { "" } }) stringY <- reactive({ if (inputY() > -999) { article <- get_indefinite_article(labelY()) paste("and", article, labelY(), "of", inputY()) } else { "" } }) stringCount <- reactive({ if (inputY() > -999 && inputX() > -999) { paste("The number of records with higher",labelX(), "and", labelY(), "is", nrow(mySubset())) } else { "" } }) ## Post the results to the chart details well. output$chartDetails <- renderUI({ if (inputX() > -999 && inputY() > -999) { HTML(paste(stringX(), "<br>", stringY(), "<br>", stringCount())) } else { HTML("Click on the chart") } }) }
额外优化提示
我注意到你的mySubset里的子集筛选代码可能有问题:subset(myData, labelX() > inputX() & labelY() > inputY())这里直接用labelX()作为列名的话,R会把它当成变量名而不是列名,所以我改成了.data[[labelX()]],这是tidyverse风格的列名引用方式,能正确解析动态的列名。
这样修改后,你的代码不仅消除了重复逻辑,还更易维护,以后如果要调整"a"/"an"的判断规则(比如处理以元音发音开头但首字母不是元音的单词,比如"hour"),只需要修改get_indefinite_article这一个函数就可以了。
内容的提问来源于stack exchange,提问作者Hester Lyons
相关产品推荐
相关产品推荐

