rdataframedata-visualizationdataviewupsetr

Stacked barplot in UpSetR


I have been looking for a way of having a stacked bar plot in an upsetR graph. I downloaded the movies data set (from here) and added a column having only two values "M" and "C". Below, information on how I loaded the data and added the "x" column.

Edit:

m <- read.csv(system.file("extdata", "movies.csv", package = "UpSetR"), 
                           header = T, sep = ";")
nrow(m)
[1] 3883
x<-c(rep("M", 3000), rep("C", 883))
m<-cbind(m, x)  
unique(m$x)
[1] M C

This is the structure of the data frame:

str(m)
'data.frame':   3883 obs. of  22 variables:
 $ Name       : Factor w/ 3883 levels "$1,000,000 Duck (1971)",..: 3577 1858 1483 3718 1175 1559 3010 3548 3363 1420 ...
 $ ReleaseDate: int  1995 1995 1995 1995 1995 1995 1995 1995 1995 1995 ...
 $ Action     : int  0 0 0 0 0 1 0 0 1 1 ...
 $ Adventure  : int  0 1 0 0 0 0 0 1 0 1 ...
 $ Children   : int  1 1 0 0 0 0 0 1 0 0 ...
 $ Comedy     : int  1 0 1 1 1 0 1 0 0 0 ...
 $ Crime      : int  0 0 0 0 0 1 0 0 0 0 ...
 $ Documentary: int  0 0 0 0 0 0 0 0 0 0 ...
 $ Drama      : int  0 0 0 1 0 0 0 0 0 0 ...
 $ Fantasy    : int  0 1 0 0 0 0 0 0 0 0 ...
 $ Noir       : int  0 0 0 0 0 0 0 0 0 0 ...
 $ Horror     : int  0 0 0 0 0 0 0 0 0 0 ...
 $ Musical    : int  0 0 0 0 0 0 0 0 0 0 ...
 $ Mystery    : int  0 0 0 0 0 0 0 0 0 0 ...
 $ Romance    : int  0 0 1 0 0 0 1 0 0 0 ...
 $ SciFi      : int  0 0 0 0 0 0 0 0 0 0 ...
 $ Thriller   : int  0 0 0 0 0 1 0 0 0 1 ...
 $ War        : int  0 0 0 0 0 0 0 0 0 0 ...
 $ Western    : int  0 0 0 0 0 0 0 0 0 0 ...
 $ AvgRating  : num  4.15 3.2 3.02 2.73 3.01 3.88 3.41 3.01 2.66 3.54 ...
 $ Watches    : int  2077 701 478 170 296 940 458 68 102 888 ...
 $ x          : Factor w/ 2 levels "M","C": 1 1 1 1 1 1 1 1 1 1 ...

Now I tried to implement the stacked bar plot as follow:

upset(m,
  queries = list(
    list(query = elements, 
         params = list("x", "M"), color = "#e69f00", active = T),
    list(query = elements, 
         params = list("x", "C"), color = "#cc79a7", active = T)))

The result looks like this:

enter image description here

As you can see the proportions are wrong as there should be in each bar only two colors (factor) either "M" or "C". This issue seems to be not a trivial one, as also pointed out here. Does anyone have an idea on how to implement this in UpsetR? Thanks a lot


Solution

  • Here is a way to create an upset plot with stacked barplot, but using my ComplexUpset rather than UpSetR:

    stacked bars complex upset

    library(ComplexUpset)
    movies = as.data.frame(ggplot2movies::movies)
    genres = colnames(movies)[18:24]
    
    # for simplicity of examples, only use the complete data points
    movies[movies$mpaa == '', 'mpaa'] = NA
    movies = na.omit(movies)
    
    
    upset(
        movies,
        genres,
        base_annotations=list(
            'Intersection size'=intersection_size(
                counts=FALSE,
                mapping=aes(fill=mpaa)
            )
        ),
        width_ratio=0.1
    )
    

    Please see more examples in the documentation. The Installation instructions are available on GitHub: krassowski/complex-upset (there is also a comparison to UpSetR and other packages).