我目前正在开发 Rshiny 应用程序。我必须使用多个选择输入和一个复选框输入来制作多个箱线图。我几乎完成了我的任务,现在我只需要做到这一点,以便每次更改所选物种时,比例保持不变(当然,除非输入了其他变量)。
我的代码如下所示:
library(shiny)
library(palmerpenguins)
library(dplyr)
library(ggplot2)
data <- na.omit(penguins)
colnames(data) <- c("Species",
"Island",
"Bill Length (mm)",
"Bill Depth (mm)",
"Flipper Length (mm)",
"Body Mass (g)",
"Sex",
"Year")
data.numeric <- data[, c(3:6, 8)]
data.categorical <- data[, c(1,7)]
ui <- fluidPage(
headerPanel("Penguin boxplots"),
selectInput("ycol",
"Numeric Variable",
names(data.numeric),
selected = names(data.numeric)[3]),
selectInput("xcol",
"Categorical Variable",
names(data.categorical),
selected = names(data.categorical)[2]),
checkboxInput("split",
"Split levels by Island",
value = FALSE),
selectInput("species",
"Species Type",
c("Unspecified", levels(data$Species))),
mainPanel(
plotOutput("plot1")
))
# 4. Use a select input to allow the user to view separate plotting
# panels for each species, with each plot panel on the same scale.
server <- function(input, output){
output$plot1 <- renderPlot({
par(mar = c(5, 4.1, 0, 1))
if (input$species == "Unspecified"){
if (input$split) {
ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]], fill = Island)) +
geom_boxplot(na.rm = TRUE) +
if (input$ycol == "Bill Length (mm)"){
coord_cartesian(ylim = c(30, 60))
} else if (input$ycol == "Bill Depth (mm)"){
coord_cartesian(ylim = c(12.5, 21.5))
} else if (input$ycol == "Flipper Length(mm)"){
coord_cartesian(ylim = c(170, 232))
} else if (input$ycol == "Body Mass (g)"){
coord_cartesian(ylim = c(2500, 6500))
} else if (input$ycol == "Year"){
coord_cartesian(ylim = c(2006, 2009))
} +
xlab(input$xcol) +
ylab(input$ycol) +
scale_x_discrete(labels = c("Female", "Male")) +
theme(text = element_text(size = 15))
} else {
ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]])) +
geom_boxplot(na.rm = TRUE) +
if (input$ycol == "Bill Length (mm)"){
coord_cartesian(ylim = c(30, 60))
} else if (input$ycol == "Bill Depth (mm)"){
coord_cartesian(ylim = c(12.5, 21.5))
} else if (input$ycol == "Flipper Length(mm)"){
coord_cartesian(ylim = c(170, 232))
} else if (input$ycol == "Body Mass (g)"){
coord_cartesian(ylim = c(2500, 6500))
} else if (input$ycol == "Year"){
coord_cartesian(ylim = c(2006, 2009))
} +
xlab(input$xcol) +
ylab(input$ycol) +
theme(text = element_text(size = 15))
}
} else {
data <- data %>%
filter(data$Species == input$species)
if (input$split) {
ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]], fill = Island)) +
geom_boxplot(na.rm = TRUE) +
xlab(input$xcol) +
ylab(input$ycol) +
scale_x_discrete(labels = c("Female", "Male")) +
theme(text = element_text(size = 15))
} else {
ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]])) +
geom_boxplot(na.rm = TRUE) +
xlab(input$xcol) +
ylab(input$ycol) +
theme(text = element_text(size = 15))
}
}
})
}
shinyApp(ui = ui, server = server)
当我运行包含 else if (input$ycol == "Year"){ coord_cartesian(ylim = c(2006, 2009))}
的行时出现以下错误: 无法将 ggproto 对象添加在一起。您是否忘记将此对象添加到 ggplot 对象中?
我不确定我哪里出了问题,或者我是否只是忽略了某种语法错误。
附:代码尚未完成 - 我仍然需要添加更多代码来控制物种不是“未指定”时的比例,但在弄清楚这一点之前我不会这样做。
最佳答案
您可以通过创建一个返回所需的 coord_cartesian 语句的函数来简化事情。然后可以像通常的 ggplot 工作流程一样使用 +
将函数添加到 ggplot 链中。
下面的示例使用了示例中的硬编码选项。但是,如果您可以提供有关如何选择这些范围的更多信息,则可以以更自动化的方式获取 y 范围,而不必显式地对每种可能的情况进行硬编码。
在下面的示例中,case_when
语句返回适当的 ylim
值以提供给 coord_cartesian
。如果 input$ycol
与任何选项都不匹配,case_when
将返回 ylim=c(NA,NA)
,这将导致 ggplot保持默认的轴范围。
# I've included only 3 choices. Add in as many additional choices as needed.
coord_fnc = function(x=input$ycol) {
ylim = dplyr::case_when(
x=="Bill Length (mm)" ~ c(30,60),
x=="Flipper Length(mm)" ~ c(170, 232),
x=="Bill Depth (mm)" ~ c(12.5,21.5)
)
coord_cartesian(ylim=ylim)
}
ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]], fill = Island)) +
geom_boxplot(na.rm = TRUE) +
coord_fnc() +
xlab(input$xcol) +
ylab(input$ycol) +
theme(text = element_text(size = 15))
使用内置的 mtcars
数据框尝试一下:
ggplot(mtcars, aes(hp, mpg)) +
geom_point() +
coord_fnc("Bill Length (mm)")
虽然 if else
语句的字符串需要大量代码,但这种方法可以工作,我不确定为什么你会收到错误(可能是代码的其他部分) )。例如,这有效:
input = list(ycol = "Year")
ggplot(mtcars, aes(hp, mpg)) +
geom_point() +
if (input$ycol == "Bill Length (mm)"){
coord_cartesian(ylim = c(30, 60))
} else if (input$ycol == "Bill Depth (mm)"){
coord_cartesian(ylim = c(12.5, 21.5))
} else if (input$ycol == "Flipper Length(mm)"){
coord_cartesian(ylim = c(170, 232))
} else if (input$ycol == "Body Mass (g)"){
coord_cartesian(ylim = c(2500, 6500))
} else if (input$ycol == "Year"){
coord_cartesian(ylim = c(2006, 2009))
}
关于r - 无法将 ggproto 对象添加在一起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65243530/