teunbrand / ggh4x

ggplot extension: options for tailored facets, multiple colourscales and miscellaneous
https://teunbrand.github.io/ggh4x/
Other
534 stars 32 forks source link

Error: Facetting variables must have at least one value #74

Closed GKok closed 1 year ago

GKok commented 1 year ago

I'm getting a new error with a script that previously worked, presumably after updating ggh4x. I tried the development build, but that didn't solve it.

I have a dataset with various variables. I'm trying to draw a figure with the following code:

plot +
facet_nested(outcome + test ~ HLA, 
                 switch="y", 
                 scales = "free_y",
                 space = "free_y") + 
[...]

This throws the following error:

Error: Facetting variables must have at least one value

However, all facetting variables have multiple values:

> levels(data$outcome)
[1] "AR"  "CR"  "GL1"
> levels(data$test)
[1] "0-1" "1-2" "0-2"
> levels(data$HLA)
[1] "A"  "B"  "C"  "DR" "DQ"

Now some facets may be empty, as not all datapoints are available for every facet. That was not a problem previously, but I'm not sure now.

Any idea what's going on? Thanks a lot for your help!

> sessionInfo()
R version 4.2.1 (2022-06-23)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Monterey 12.5

Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRlapack.dylib

locale:
[1] nl_NL.UTF-8/nl_NL.UTF-8/nl_NL.UTF-8/C/nl_NL.UTF-8/nl_NL.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] ggh4x_0.2.1.9000 ggpubr_0.4.0     extrafont_0.18   forcats_0.5.1    stringr_1.4.0    dplyr_1.0.9     
 [7] purrr_0.3.4      readr_2.1.2      tidyr_1.2.0      tibble_3.1.8     tidyverse_1.3.2  gdata_2.18.0.1  
[13] ggalt_0.6.2      scales_1.2.0     ggplot2_3.3.6   

loaded via a namespace (and not attached):
 [1] lubridate_1.8.0     gtools_3.9.3        assertthat_0.2.1    proj4_1.0-11        utf8_1.2.2         
 [6] R6_2.5.1            cellranger_1.1.0    backports_1.4.1     reprex_2.0.1        httr_1.4.3         
[11] pillar_1.8.0        rlang_1.0.4         googlesheets4_1.0.0 curl_4.3.2          readxl_1.4.0       
[16] rstudioapi_0.13     car_3.1-0           extrafontdb_1.0     googledrive_2.0.0   munsell_0.5.0      
[21] broom_1.0.0         compiler_4.2.1      modelr_0.1.8        pkgconfig_2.0.3     tidyselect_1.1.2   
[26] fansi_1.0.3         crayon_1.5.1        tzdb_0.3.0          dbplyr_2.2.1        withr_2.5.0        
[31] MASS_7.3-58.1       grid_4.2.1          jsonlite_1.8.0      Rttf2pt1_1.3.10     gtable_0.3.0       
[36] lifecycle_1.0.1     DBI_1.1.3           magrittr_2.0.3      KernSmooth_2.23-20  carData_3.0-5      
[41] cli_3.3.0           stringi_1.7.8       ggsignif_0.6.3      fs_1.5.2            remotes_2.4.2      
[46] xml2_1.3.3          ellipsis_0.3.2      generics_0.1.3      vctrs_0.4.1         ash_1.0-15         
[51] RColorBrewer_1.1-3  tools_4.2.1         glue_1.6.2          maps_3.4.0          hms_1.1.1          
[56] abind_1.4-5         colorspace_2.0-3    gargle_1.2.0        BiocManager_1.30.18 rstatix_0.7.0      
[61] rvest_1.0.2         haven_2.5.0     
teunbrand commented 1 year ago

It is hard to know without a reproducible example, but my guess is that data isn't the only data provided to the plot and some other part might be missing some of the facetting variables.

GKok commented 1 year ago

Not sure if it's op any help, but here's a reprex-output. It shows many errors, but the Excel-file is properly loaded, despite what it shows.

library(ggplot2)
library(scales)
library(ggalt)
#> Registered S3 methods overwritten by 'ggalt':
#>   method                  from   
#>   grid.draw.absoluteGrob  ggplot2
#>   grobHeight.absoluteGrob ggplot2
#>   grobWidth.absoluteGrob  ggplot2
#>   grobX.absoluteGrob      ggplot2
#>   grobY.absoluteGrob      ggplot2
library(gdata)
#> gdata: read.xls support for 'XLS' (Excel 97-2004) files ENABLED.
#> 
#> gdata: read.xls support for 'XLSX' (Excel 2007+) files ENABLED.
#> 
#> Attaching package: 'gdata'
#> The following object is masked from 'package:stats':
#> 
#>     nobs
#> The following object is masked from 'package:utils':
#> 
#>     object.size
#> The following object is masked from 'package:base':
#> 
#>     startsWith
library(tidyverse)
library(extrafont)
#> Registering fonts with R
library(ggpubr)
library(grDevices)
#remotes::install_github("teunbrand/ggh4x")
library(ggh4x)
library(reprex)

theme_set(theme_minimal(base_family="Myriad Pro"))
theme_update(text = element_text(family = "Myriad Pro"))

data = read.xls('Data-HLA.xlsx')
#> Warning in system(cmd, intern = !verbose): running command ''/usr/bin/perl'
#> '/Library/Frameworks/R.framework/Versions/4.2/Resources/library/gdata/perl/
#> xls2csv.pl' 'Data-HLA.xlsx' '/var/folders/hl/ljvw4xb15_b2ff_y5ts5vpb80000gn/T//
#> RtmpRMmNqE/file3a101cb0ca3c.csv' '1'' had status 2
#> Error in xls2sep(xls, sheet, verbose = verbose, ..., method = method, : Intermediate file '/var/folders/hl/ljvw4xb15_b2ff_y5ts5vpb80000gn/T//RtmpRMmNqE/file3a101cb0ca3c.csv' missing!
#> Error in file.exists(tfn): invalid 'file' argument
#data = read.xls('Data-HLA-supplement.xlsx')
data$test <- forcats::fct_inorder(data$test)
#> Error in data$test: object of type 'closure' is not subsettable
data$HLA <- forcats::fct_inorder(data$HLA)
#> Error in data$HLA: object of type 'closure' is not subsettable
data$outcome <- forcats::fct_inorder(data$outcome)
#> Error in data$outcome: object of type 'closure' is not subsettable
data <- data %>% arrange(year, author) %>% mutate(year=forcats::fct_inorder(factor(year))) %>% arrange(-row_number())
#> Error in UseMethod("arrange"): no applicable method for 'arrange' applied to an object of class "function"
data$author_year <- forcats::fct_inorder(paste(data$author, data$year))
#> Error in data$author: object of type 'closure' is not subsettable
data$author_year <- forcats::fct_inorder(str_replace(data$author_year, " NA", ""))
#> Error in data$author_year: object of type 'closure' is not subsettable

plot_outcome <- function (dataset) {
  plot <- ggplot(na.omit(dataset), aes(y=author_year, color=shape))

  plot + 
    scale_x_log10(limits = c(0.01, 100),
                  breaks = scales::trans_breaks("log10", function(x) 10^x),
                  labels = ~ gsub("\\.?0+$", "", comma(.x))) +
    geom_vline(aes(xintercept=1), 
               linetype="dotted") +
    theme(panel.grid.major.x=element_line(size=0.5),
          panel.grid.minor.x=element_blank(),
          axis.title.y=element_blank(),
          strip.placement = "outside",
          strip.text.x = element_text(face = "bold"),
          strip.text.y = element_text(face = "bold"),
          strip.background = element_rect(colour = "white", fill = "gray95"),
          panel.spacing.x = unit(1,"line")) +
    facet_nested(outcome + test ~ HLA, 
                 switch="y", 
                 labeller = labeller(outcome = c("AR" = "Acute rejection",
                                                 "CR" = "Chronic rejection",
                                                 "GL1" = "Graft failure (1-year)",
                                                 "GL2" = "Graft failure (2-year)",
                                                 "GL5" = "Graft failure (5-year)",
                                                 "M1" = "Mortality (1-year)",
                                                 "M5" = "Mortality (5-year)"),
                                     test = c("0-1" = "0 vs. 1 MM",
                                              "0-2" = "0 vs. 2 MM",
                                             "1-2" = "1 vs. 2 MM"),
                                     HLA = c("A" = "HLA-A",
                                             "B" = "HLA-B",
                                             "C" = "HLA-C",
                                             "DR" = "HLA-DR",
                                             "DQ" = "HLA-DQ")),
                 scales = "free_y",
                 space = "free_y"
               ) +
    scale_size(guide="none") +
    scale_shape_manual(values = c(18,16),
                       guide="none") +
    scale_colour_manual(values = c(2, 1),
                        guide="none") +
    labs(x="Relative risk") +
    geom_point(aes(x=RR, 
                   size=weight, 
                   shape=as.factor(shape)),
               position = position_dodge(width=0.8)) +
    geom_dumbbell(aes(x=ifelse(CI.lower < 0.01, 0.01, CI.lower), 
                      xend=ifelse(CI.upper > 100, 100, CI.upper)), 
                  size_x=0, 
                  size_xend=0, 
                  position = position_dodgev(height=-0.8)) +
    geom_segment(aes(x = ifelse(CI.upper > 100, 99, NA), 
                     xend = ifelse(CI.upper > 100, 100, NA),
                     yend=author_year),
                 arrow = arrow(length = unit(0.15, "cm"))) +
    geom_text(aes(x = RR+2, 
                  label=ifelse(is.na(P), "", paste0("RR = ", comma(RR, accuracy = 0.01), " [", comma(CI.lower, accuracy = 0.01), "-", comma(CI.upper, accuracy = 0.01), "]\nP = ", comma(P, accuracy = 0.01)))), 
              color="black", 
              position = position_dodge(width=0.8), 
              size=3, 
              hjust = 0, 
              fontfamily="Myriad Pro")
}

plotall <- plot_outcome(data)
#> Error in `ggplot()`:
#> !   You're passing a function as global data.
#>   Have you misspelled the `data` argument in `ggplot()`
plotall
#> Error in eval(expr, envir, enclos): object 'plotall' not found

I have also attached the Excel file.

This exact script + datafile worked previously to create the attached plot.

Many thanks!

teunbrand commented 1 year ago

From executing your code, I gather that na.omit() drops every row of the dataset. So indeed, the facetting variables do not have a value. You get the same error when you use facet_grid(), so I don't think this is an issue with ggh4x.

For future reference, people diagnosing possible problems with code would think it is great if reprexes are more minimal. Now, I had to install several packages I don't use just to run the code, and weed through many lines of code that weren't relevant to the problem (I know this sounds grumpy, but it's not intended this way :D). This specific example could have been the following reprex:

library(ggplot2)
library(ggh4x)

plot_outcome <- function(dataset) {
  ggplot(na.omit(dataset), aes(Sepal.Width, Sepal.Length)) +
    geom_point() +
    facet_nested(~ Species)
}

plot_outcome(cbind(iris, na_col = NA))
#> Error: Facetting variables must have at least one value
GKok commented 1 year ago

Thank you Teun.

My apologies for the issue not being related; I missed that, presumably because the exact same code worked previously and I was too focussed on facet_nested(). And I'll take your advice and will make a more specific/short reprex.

I appreciate your work. Have a good weekend!