facet_grid in Shiny flexdashboard giving error “Faceting variables must have at least one value”

扶醉桌前 提交于 2019-12-18 07:04:51

问题


I am having some trouble getting a ggplot2 facet_grid plot working for an evaluation system. The plot renders well but I get the following error in the browser and console:

Error in : Faceting variables must have at least one value

This occurs every time I switch the brand entry based on the input input$brand. The application doesn't crash but the error message is annoying.

I have prepared this reproducible example:

---
title: "Power ranking for mtcars"
runtime: shiny
output:
  flexdashboard::flex_dashboard:
    orientation: rows
    source_code: embed
---



```{r rows.print = 25}
library(dplyr)
library(ggplot2)

mtcars_tidy <- mtcars %>% 
    tibble::rownames_to_column() %>% 
    rename(model = rowname) %>% 
    mutate(brand = gsub( " .*$", "", model )) %>% 
    mutate(model = model) %>% 
    select(brand, model,  everything())  %>% 
    tidyr::gather(key = 'measure', value = "value", mpg:carb) %>%
    mutate(ranking = as.factor(sample(x = c(1, 2, 3), size = n(), replace = TRUE))) %>%

    mutate(power = case_when(
        .$measure == "hp" & value > 200 | (.$measure == "cyl" & value == 8) ~ "high",
        .$measure == "hp" & value < 200 | (.$measure == "cyl" & value == 8) ~ "medium",
        .$measure == "hp" & value > 100 | (.$measure == "cyl" & value == 6) ~ "high",
        .$measure == "hp" & value < 100 | (.$measure == "cyl" & value == 6) ~ "medium",
        .$measure == "hp" & value > 50  | (.$measure == "cyl" & value == 6) ~ "high",
        .$measure == "hp" & value < 50  | (.$measure == "cyl" & value == 6) ~ "medium",

        .$measure == "hp" & value > 200 | (.$measure == "carb" & value >  4) ~ "high",
        .$measure == "hp" & value < 200 | (.$measure == "carb" & value <= 4) ~ "medium",
        .$measure == "hp" & value > 100 | (.$measure == "carb" & value >  2.8) ~ "high",
        .$measure == "hp" & value < 100 | (.$measure == "carb" & value <= 2.8) ~ "medium",
        .$measure == "hp" & value > 50  | (.$measure == "carb" & value > 2) ~ "high",
        .$measure == "hp" & value < 50  | (.$measure == "carb" & value <= 2) ~ "medium",
        TRUE ~ "low"
    )) 
```

# Sidebar {.sidebar data-width="350"}

```{r}
selectInput("brand", "Brand of the car", 
            choices = unique(mtcars_tidy$brand))

renderUI({
    selectInput("model", "Car model",
                choices = mtcars_tidy$model[mtcars_tidy$brand == levels(mtcars_tidy$brand)[1]])
})

br()

observe({
    brand <- input$brand
    updateSelectInput(session, "model", 
                      choices = mtcars_tidy$model[mtcars_tidy$brand == brand])
})    


# when switching the brand of the car, input$brand this error pops up:
# Error in : Faceting variables must have at least one value
```


# Main

##

### Plot power ranking for each measure

```{r}
nameorder <- make.unique(mtcars_tidy$measure[order(mtcars_tidy$power, mtcars_tidy$ranking)])
mtcars_tidy$measure <- factor(mtcars_tidy$measure, levels=nameorder, 
                                   ordered = TRUE)

dataset <- reactive({
    subset(mtcars_tidy, brand == input$brand & model == input$model) 
})


renderPlot({
    ggplot(dataset(), aes(x = ranking, y = measure)) +
        geom_segment(aes(yend = measure), xend=0, color = "grey50") +
        geom_point(size = 3, aes(colour = power)) +
        scale_colour_brewer(palette="Set1", limits = c("high","medium", "low")) +
        theme_bw() +
        theme(panel.grid.major.y = element_blank()) +   # No horizontal grid lines
        facet_grid(power ~ ., scales="free_y", space="free_y") +
        ggtitle(paste0("Brand: ", input$brand, ", Model: " , input$model))
})    
```

EDIT 1: I changed facet_grid to facet_wrap but the error still there.

EDIT 2: As per suggestion, I switched to facet_wrap with this formula: p <- p + facet_wrap(power ~ .). Still same error. I also tried this other formula p <- p + facet_wrap(power ~ ranking). Error still there.

EDIT 3: On the facet_wrap function I also tried with these formulas as well:

  • facet_wrap(~power )
  • facet_wrap(vars(power ))
  • facet_wrap(vars(power , ranking)).

The error is still the same (identical). No change (Error in : Faceting variables must have at least one value).

EDIT 4: If I try with facet_wrap(power), the error is even worse because crashes Shiny with this mouthful:

Error: Column `function (lambda = 1) \n{\n    if (!is.numeric(lambda) || is.na(lambda)) \n        stop("invalid argument 'lambda'")\n    if (lambda <= 0) \n        return(make.link("log"))\n    if (lambda == 1) \n        return(make.link("identity"))\n    linkfun <- function(mu) mu^lambda\n    linkinv <- function(eta) pmax(eta^(1/lambda), .Machine$double.eps)\n    mu.eta <- function(eta) pmax((1/lambda) * eta^(1/lambda - \n        1), .Machine$double.eps)\n    valideta <- function(eta) all(is.finite(eta)) && all(eta > \n        0)\n    link <- paste0("mu^", round(lambda, 3))\n    structure(list(linkfun = linkfun, linkinv = linkinv, mu.eta = mu.eta, \n        valideta = valideta, name = link), class = "link-glm")\n}` must be a 1d atomic vector or a list

回答1:


This error is occuring when dataset() has no rows in it. When I run your code (the current version with the facet_grid(power ~ .,), it actually works fine. When I choose a new brand, there is a short gap where it displays this error while the input$model list updates. Once it does, and the combination of brand and model return rows, the plot displays nicely.

You can prevent this gap by using req to hold off rendering the plot until certain requirements are met. Just insert the following code at the top of your renderPlot

req(nrow(dataset()) > 0)

This will prevent the renderPlot from running if dataset() doesn't contain at least one row. In that case, the plot will just be blank (removing the scary error message) until the data is ready to use. With that line added, your app seems to be running fine (and looks quite nice, by the way).


You can see the source of that error message by testing your code outside the shiny context. Here's a minimal example of your plot:

ggplot(dataset, aes(x = ranking, y = measure)) +
        geom_segment(aes(yend = measure), xend=0, color = "grey50") +
        geom_point(size = 3, aes(colour = power)) +
        facet_grid(power ~ ., scales="free_y", space="free_y")

when I make dataset using this call:

dataset <- subset(mtcars_tidy, brand == 'Honda' & model == 'Honda Civic')

The plot renders correctly. When I use a subset that doesn't return any rows:

dataset <- subset(mtcars_tidy, brand == 'Honda' & model == 'Civic')

I get your same error:

Error: Faceting variables must have at least one value



来源:https://stackoverflow.com/questions/51427189/facet-grid-in-shiny-flexdashboard-giving-error-faceting-variables-must-have-at

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!