如何根据多个用户定义的输入在RShiny中Map图例?

j8ag8udp  于 2023-03-27  发布在  其他
关注(0)|答案(1)|浏览(86)

我正在使用以下形式的土壤水分数据集:

structure(list(DATE = c("1966-09-14", "1966-09-14", "1966-09-14", 
"1966-09-14", "1966-09-14", "1966-09-14"), LOCATION = c("S1S", 
"S2W", "S3E", "S3W", "S4S", "S5"), D_15 = c(NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_), D_46 = c(3.81, 3.05, 
1.52, 1.37, 1.75, 1.6), D_76 = c(2.13, 2.97, 0.91, 0.91, 1.68, 
3.28), D_107 = c(2.67, 2.97, 2.67, 2.51, 2.97, 3.73), D_137 = c(2.44, 
2.74, 3.81, 4.11, 3.28, 3.43), D_168 = c(2.74, 2.9, 1.37, 4.27, 
3.96, 2.67), D_198 = c(2.44, 3.51, 2.97, 3.2, 2.74, 2.59), D_229 = c(2.74, 
3.81, 1.83, 4.88, 3.51, 3.05), D_259 = c(10.36, 3.12, 1.52, 3.43, 
2.67, NA), D_290 = c(11.51, 1.45, 0.46, 6.25, 2.59, NA), D_320 = c(11.05, 
2.9, NA, 5.79, NA, NA)), row.names = c(NA, 6L), class = "data.frame")

其中LOCATION表示分水岭,D_15、D_46、等是土壤水分深度。我试图创建一个应用程序,允许用户绘制位置和深度的各种组合,以便可以比较一个站点的所有深度,或者可以比较不同流域的相同深度。我卡住的地方是实现图例。我希望图例根据场地和深度的组合而变化。当LOCATION相同但深度不同时,是否有任何方法将图例美学Map为子集数据框和用户定义的土壤深度的组合(或反之亦然)它们在图例中分别绘制和标记??下面是我当前的server.R和ui.R配置。
x一个一个一个一个x一个一个二个x
我尝试为每个输入添加一个geom_point,颜色由土壤深度Map,但这会导致相同的问题,即当两个深度相同时,它们在图例中Map相同。

vbkedwbf

vbkedwbf1#

这是解决你问题的办法。
根据您发布的示例数据,以下是整理数据的方法:

df <- as_tibble(df) %>% 
        mutate(DATE=as.Date(DATE)) %>% 
        pivot_longer(
          starts_with("D_"), 
          names_to="Depth", 
          values_to="Moisture", 
          names_prefix="D_"
        ) %>% 
        mutate(Depth=as.numeric(Depth))
df
# A tibble: 66 × 4
   DATE       LOCATION Depth Moisture
   <date>     <chr>    <dbl>    <dbl>
 1 1966-09-14 S1S         15    NA   
 2 1966-09-14 S1S         46     3.81
 3 1966-09-14 S1S         76     2.13
 4 1966-09-14 S1S        107     2.67
 5 1966-09-14 S1S        137     2.44
 6 1966-09-14 S1S        168     2.74
 7 1966-09-14 S1S        198     2.44
 8 1966-09-14 S1S        229     2.74
 9 1966-09-14 S1S        259    10.4 
10 1966-09-14 S1S        290    11.5 
# … with 56 more rows

现在,您的UI可以大大简化:你只需要一个用于深度的小部件和一个用于位置的小部件,前提是你将multiple=TRUE添加到每个小部件中。你也只需要一个过滤的数据集。
我强烈反对使用xlim按日期过滤。如果你想在生成图时进行过滤,请使用coord_cartesianxlim过滤数据集,然后生成图。coord_cartesian生成图,然后“缩放”到请求的区域。在这里,这没有什么区别,但如果你以任何方式估算或建模,xlim(和ylim)会产生意想不到的错误结果,而且原因可能很难调试。
第三种选择是在构造过滤数据集时按日期进行过滤,这就是我在这里选择做的。
由于您只提供了一个日期的数据,因此我在您的图中添加了geom_point,以便您可以实际看到一些内容。
最后,如果您愿意,可以通过提供长度为2的向量作为value参数来创建单个日期范围sliderInput

ui <- fluidPage(
  titlePanel(
    "MEF Data Explorer"),
    title = "MEF Data Explorer",
    plotOutput('Plot'),
    hr(),
    fluidRow(
      column(
        3,
        h4("SELECT DATE RANGE"),
        sliderInput(
          "mindate", 
          "Min date:", 
          min = min(df$DATE), 
          max = max(df$DATE), 
          value = min(df$DATE)
        ),
        sliderInput(
          "maxdate", 
          "Max date:", 
          min = min(df$DATE), 
          max = max(df$DATE), 
          value = max(df$DATE)
        )
    ),
    column(
      4,
      h4("SELECT SITE"),
      selectInput(
        inputId = "subset", 
        label = NULL, 
        choices = c(" ", unique(df$LOCATION)), 
        multiple=TRUE
      )
    ),
    column(
      4,
      h4("SELECT DEPTH"),
      selectInput(
        inputId = "depth", 
        label = NULL, 
        choices = unique(df$Depth), 
        multiple=TRUE
      )
    )
  )
)

server <- function(input, output) {
  ## filter df by LOCATION
  filtered_data <- reactive({
    df %>% filter(
             LOCATION %in% input$subset, 
             Depth %in% as.numeric(input$depth),
             between(DATE, input$mindate, input$maxdate)
           )
  })
  
  ## ggplot selected data 
  output$Plot <- renderPlot({
    filtered_data() %>% 
      ggplot(aes(x = DATE, y=Moisture, colour=as.factor(Depth))) + 
        geom_line() +
        geom_point() +
        theme_light()
  })
}

shinyApp(ui, server)

相关问题