Lifecycle:maturing

Brings SummarizedExperiment to the tidyverse!

website: stemangiola.github.io/tidySummarizedExperiment/

Please also have a look at

Introduction

tidySummarizedExperiment provides a bridge between Bioconductor SummarizedExperiment (Morgan et al. 2020) and the tidyverse (Wickham et al. 2019) as part of the tidyomics ecosystem (Hutchison et al. 2024). It creates an invisible layer that enables viewing the Bioconductor SummarizedExperiment object as a tidyverse tibble, and provides SummarizedExperiment-compatible dplyr, tidyr, ggplot and plotly functions. This allows users to get the best of both Bioconductor and tidyverse worlds.

Functions/utilities available

SummarizedExperiment-compatible Functions Description
all After all tidySummarizedExperiment is a SummarizedExperiment object, just better
tidyverse Packages Description
dplyr Almost all dplyr APIs like for any tibble
tidyr Almost all tidyr APIs like for any tibble
ggplot2 ggplot like for any tibble
plotly plot_ly like for any tibble
Utilities Description
as_tibble Convert cell-wise information to a tbl_df

Installation

if (!requireNamespace("BiocManager", quietly=TRUE)) {
      install.packages("BiocManager")
  }

BiocManager::install("tidySummarizedExperiment")

From Github (development)

remotes::install_github("tidyomics/tidySummarizedExperiment")

Load libraries used in the examples.

Opting In and Out of Tidy Print

By default, the standard SummarizedExperiment print format is used. You can opt in to use the tidy tibble-style display, and opt out at any time. The setting can be configured for the current R session only, or saved to persist across sessions.

Opt In to Tidy Print

To enable the tidy print format, use tidy_print_on(). By default, this only affects the current R session:

# Enable tidy print for current session only
tidy_print_on()
pasilla_tidy  # Will display with tidy tibble-style format

If you want the setting to persist across R sessions, use remember = TRUE:

# Enable tidy print and remember the setting
tidy_print_on(remember = TRUE)

Opt Out of Tidy Print

To return to the standard SummarizedExperiment print format, use tidy_print_off(). By default, this only affects the current session:

# Disable tidy print for current session only
tidy_print_off()

To permanently disable tidy print and clear any saved preference:

tidy_print_off(remember = TRUE)

tidySummarizedExperiment, the best of two worlds!

This is a SummarizedExperiment object but it is evaluated as a tibble. So it is fully compatible both with SummarizedExperiment and tidyverse APIs.

pasilla_tidy <- tidySummarizedExperiment::pasilla 

It looks like a tibble

tidy_print_on()
pasilla_tidy
## # A SummarizedExperiment-tibble abstraction: Features=14599 | Samples=7 | 
## #   Assays=counts
## #                                   |------ COVARIATES ----|
##        .feature    .sample | counts | condition type       |
##        <chr>       <chr>   | <chr>  | <chr>     <chr>      |
## 1      FBgn0000003 untrt1  | 0      | untreated single_end |
## 2      FBgn0000008 untrt1  | 92     | untreated single_end |
## 3      FBgn0000014 untrt1  | 5      | untreated single_end |
## 4      FBgn0000015 untrt1  | 0      | untreated single_end |
## 5      FBgn0000017 untrt1  | 4664   | untreated single_end |
##        --------    ------- - ------ - --------- ----       -
## 102189 FBgn0261571 trt3    | 0      | treated   paired_end |
## 102190 FBgn0261572 trt3    | 3      | treated   paired_end |
## 102191 FBgn0261573 trt3    | 1908   | treated   paired_end |
## 102192 FBgn0261574 trt3    | 3047   | treated   paired_end |
## 102193 FBgn0261575 trt3    | 4      | treated   paired_end |

But it is a SummarizedExperiment object after all

assays(pasilla_tidy)
## List of length 1
## names(1): counts

Tidyverse commands

We can use tidyverse commands to explore the tidy SummarizedExperiment object.

We can use slice to choose rows by position, for example to choose the first row.

pasilla_tidy %>%
    dplyr::slice(1)
## # A SummarizedExperiment-tibble abstraction: Features=1 | Samples=1 | 
## #   Assays=counts
## #                              |------ COVARIATES ----|
##   .feature    .sample | counts | condition type       |
##   <chr>       <chr>   |  <int> | <chr>     <chr>      |
## 1 FBgn0000003 untrt1  |      0 | untreated single_end |

We can use filter to choose rows by criteria.

pasilla_tidy %>%
    filter(condition == "untreated")
## # A SummarizedExperiment-tibble abstraction: Features=14599 | Samples=4 | 
## #   Assays=counts
## #                                  |------ COVARIATES ----|
##       .feature    .sample | counts | condition type       |
##       <chr>       <chr>   | <chr>  | <chr>     <chr>      |
## 1     FBgn0000003 untrt1  | 0      | untreated single_end |
## 2     FBgn0000008 untrt1  | 92     | untreated single_end |
## 3     FBgn0000014 untrt1  | 5      | untreated single_end |
## 4     FBgn0000015 untrt1  | 0      | untreated single_end |
## 5     FBgn0000017 untrt1  | 4664   | untreated single_end |
##       --------    ------- - ------ - --------- ----       -
## 58392 FBgn0261571 untrt4  | 0      | untreated paired_end |
## 58393 FBgn0261572 untrt4  | 11     | untreated paired_end |
## 58394 FBgn0261573 untrt4  | 1612   | untreated paired_end |
## 58395 FBgn0261574 untrt4  | 2819   | untreated paired_end |
## 58396 FBgn0261575 untrt4  | 3      | untreated paired_end |

We can use select to choose columns.

pasilla_tidy %>%
    select(.sample)
## # A tibble: 102,193 × 1
##    .sample
##    <chr>  
##  1 untrt1 
##  2 untrt1 
##  3 untrt1 
##  4 untrt1 
##  5 untrt1 
##  6 untrt1 
##  7 untrt1 
##  8 untrt1 
##  9 untrt1 
## 10 untrt1 
## # ℹ 102,183 more rows

We can use count to count how many rows we have for each sample.

pasilla_tidy %>%
    dplyr::count(.sample)
## # A tibble: 7 × 2
##   .sample     n
##   <chr>   <int>
## 1 trt1    14599
## 2 trt2    14599
## 3 trt3    14599
## 4 untrt1  14599
## 5 untrt2  14599
## 6 untrt3  14599
## 7 untrt4  14599

We can use distinct to see what distinct sample information we have.

pasilla_tidy %>%
    distinct(.sample, condition, type)
## # A tibble: 7 × 3
##   .sample condition type      
##   <chr>   <chr>     <chr>     
## 1 untrt1  untreated single_end
## 2 untrt2  untreated single_end
## 3 untrt3  untreated paired_end
## 4 untrt4  untreated paired_end
## 5 trt1    treated   single_end
## 6 trt2    treated   paired_end
## 7 trt3    treated   paired_end

We could use rename to rename a column. For example, to modify the type column name.

pasilla_tidy %>%
    dplyr::rename(sequencing=type)
## # A SummarizedExperiment-tibble abstraction: Features=14599 | Samples=7 | 
## #   Assays=counts
## #                                   |------ COVARIATES ----|
##        .feature    .sample | counts | condition sequencing |
##        <chr>       <chr>   | <chr>  | <chr>     <chr>      |
## 1      FBgn0000003 untrt1  | 0      | untreated single_end |
## 2      FBgn0000008 untrt1  | 92     | untreated single_end |
## 3      FBgn0000014 untrt1  | 5      | untreated single_end |
## 4      FBgn0000015 untrt1  | 0      | untreated single_end |
## 5      FBgn0000017 untrt1  | 4664   | untreated single_end |
##        --------    ------- - ------ - --------- ---------- -
## 102189 FBgn0261571 trt3    | 0      | treated   paired_end |
## 102190 FBgn0261572 trt3    | 3      | treated   paired_end |
## 102191 FBgn0261573 trt3    | 1908   | treated   paired_end |
## 102192 FBgn0261574 trt3    | 3047   | treated   paired_end |
## 102193 FBgn0261575 trt3    | 4      | treated   paired_end |

We could use mutate to create a column. For example, we could create a new type column that contains single and paired instead of single_end and paired_end.

pasilla_tidy %>%
    mutate(type=gsub("_end", "", type))
## # A SummarizedExperiment-tibble abstraction: Features=14599 | Samples=7 | 
## #   Assays=counts
## #                                   |---- COVARIATES --|
##        .feature    .sample | counts | condition type   |
##        <chr>       <chr>   | <chr>  | <chr>     <chr>  |
## 1      FBgn0000003 untrt1  | 0      | untreated single |
## 2      FBgn0000008 untrt1  | 92     | untreated single |
## 3      FBgn0000014 untrt1  | 5      | untreated single |
## 4      FBgn0000015 untrt1  | 0      | untreated single |
## 5      FBgn0000017 untrt1  | 4664   | untreated single |
##        --------    ------- - ------ - --------- ----   -
## 102189 FBgn0261571 trt3    | 0      | treated   paired |
## 102190 FBgn0261572 trt3    | 3      | treated   paired |
## 102191 FBgn0261573 trt3    | 1908   | treated   paired |
## 102192 FBgn0261574 trt3    | 3047   | treated   paired |
## 102193 FBgn0261575 trt3    | 4      | treated   paired |

We could use unite to combine multiple columns into a single column.

pasilla_tidy %>%
    unite("group", c(condition, type))
## # A SummarizedExperiment-tibble abstraction: Features=14599 | Samples=7 | 
## #   Assays=counts
## #                                   |------ COVARIATES ----|
##        .feature    .sample | counts | group                |
##        <chr>       <chr>   | <chr>  | <chr>                |
## 1      FBgn0000003 untrt1  | 0      | untreated_single_end |
## 2      FBgn0000008 untrt1  | 92     | untreated_single_end |
## 3      FBgn0000014 untrt1  | 5      | untreated_single_end |
## 4      FBgn0000015 untrt1  | 0      | untreated_single_end |
## 5      FBgn0000017 untrt1  | 4664   | untreated_single_end |
##        --------    ------- - ------ - -----                -
## 102189 FBgn0261571 trt3    | 0      | treated_paired_end   |
## 102190 FBgn0261572 trt3    | 3      | treated_paired_end   |
## 102191 FBgn0261573 trt3    | 1908   | treated_paired_end   |
## 102192 FBgn0261574 trt3    | 3047   | treated_paired_end   |
## 102193 FBgn0261575 trt3    | 4      | treated_paired_end   |

We can use append_samples to combine multiple SummarizedExperiment objects by samples. It is equivalent to cbind but it is a tidyverse-like function.

# Create two subsets of the data
pasilla_subset1 <- pasilla_tidy %>%
    filter(condition == "untreated")

pasilla_subset2 <- pasilla_tidy %>%
    filter(condition == "treated")

# Combine them using append_samples
combined_data <- append_samples(pasilla_subset1, pasilla_subset2)
combined_data
## # A SummarizedExperiment-tibble abstraction: Features=14599 | Samples=7 | 
## #   Assays=counts
## #                                   |------ COVARIATES ----|
##        .feature    .sample | counts | condition type       |
##        <chr>       <chr>   | <chr>  | <chr>     <chr>      |
## 1      FBgn0000003 untrt1  | 0      | untreated single_end |
## 2      FBgn0000008 untrt1  | 92     | untreated single_end |
## 3      FBgn0000014 untrt1  | 5      | untreated single_end |
## 4      FBgn0000015 untrt1  | 0      | untreated single_end |
## 5      FBgn0000017 untrt1  | 4664   | untreated single_end |
##        --------    ------- - ------ - --------- ----       -
## 102189 FBgn0261571 trt3    | 0      | treated   paired_end |
## 102190 FBgn0261572 trt3    | 3      | treated   paired_end |
## 102191 FBgn0261573 trt3    | 1908   | treated   paired_end |
## 102192 FBgn0261574 trt3    | 3047   | treated   paired_end |
## 102193 FBgn0261575 trt3    | 4      | treated   paired_end |

We can also combine commands with the tidyverse pipe %>%.

For example, we could combine group_by and summarise to get the total counts for each sample.

pasilla_tidy %>%
    group_by(.sample) %>%
    summarise(total_counts=sum(counts))
## # A tibble: 7 × 2
##   .sample total_counts
##   <chr>          <int>
## 1 trt1        18670279
## 2 trt2         9571826
## 3 trt3        10343856
## 4 untrt1      13972512
## 5 untrt2      21911438
## 6 untrt3       8358426
## 7 untrt4       9841335

We could combine group_by, mutate and filter to get the transcripts with mean count > 0.

pasilla_tidy %>%
    group_by(.feature) %>%
    mutate(mean_count=mean(counts)) %>%
    filter(mean_count > 0)
## # A tibble: 86,513 × 6
## # Groups:   .feature [12,359]
##    .feature    .sample counts condition type       mean_count
##    <chr>       <chr>    <int> <chr>     <chr>           <dbl>
##  1 FBgn0000003 untrt1       0 untreated single_end      0.143
##  2 FBgn0000008 untrt1      92 untreated single_end     99.6  
##  3 FBgn0000014 untrt1       5 untreated single_end      1.43 
##  4 FBgn0000015 untrt1       0 untreated single_end      0.857
##  5 FBgn0000017 untrt1    4664 untreated single_end   4672.   
##  6 FBgn0000018 untrt1     583 untreated single_end    461.   
##  7 FBgn0000022 untrt1       0 untreated single_end      0.143
##  8 FBgn0000024 untrt1      10 untreated single_end      7    
##  9 FBgn0000028 untrt1       0 untreated single_end      0.429
## 10 FBgn0000032 untrt1    1446 untreated single_end   1085.   
## # ℹ 86,503 more rows

Plotting

my_theme <-
    list(
        scale_fill_brewer(palette="Set1"),
        scale_color_brewer(palette="Set1"),
        theme_bw() +
            theme(
                panel.border=element_blank(),
                axis.line=element_line(),
                panel.grid.major=element_line(size=0.2),
                panel.grid.minor=element_line(size=0.1),
                text=element_text(size=12),
                legend.position="bottom",
                aspect.ratio=1,
                strip.background=element_blank(),
                axis.title.x=element_text(margin=margin(t=10, r=10, b=10, l=10)),
                axis.title.y=element_text(margin=margin(t=10, r=10, b=10, l=10))
            )
    )

We can treat pasilla_tidy as a normal tibble for plotting.

Here we plot the distribution of counts per sample.

pasilla_tidy %>%
    ggplot(aes(counts + 1, group=.sample, color=`type`)) +
    geom_density() +
    scale_x_log10() +
    my_theme

Session Info

## R version 4.6.1 (2026-06-24)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.4 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: UTC
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats4    stats     graphics  grDevices utils     datasets  methods  
## [8] base     
## 
## other attached packages:
##  [1] tidyr_1.3.2                     tidySummarizedExperiment_1.23.2
##  [3] ttservice_0.5.3                 SummarizedExperiment_1.43.0    
##  [5] Biobase_2.73.2                  GenomicRanges_1.65.1           
##  [7] Seqinfo_1.3.0                   IRanges_2.47.2                 
##  [9] S4Vectors_0.51.6                BiocGenerics_0.59.12           
## [11] generics_0.1.4                  MatrixGenerics_1.25.0          
## [13] matrixStats_1.5.0               dplyr_1.2.1                    
## [15] ggplot2_4.0.3                   knitr_1.51                     
## 
## loaded via a namespace (and not attached):
##  [1] gtable_0.3.6        xfun_0.60           bslib_0.12.0       
##  [4] htmlwidgets_1.6.4   lattice_0.23-1      vctrs_0.7.3        
##  [7] tools_4.6.1         tidyprint_1.1.0     tibble_3.3.1       
## [10] fansi_1.0.7         pkgconfig_2.0.3     Matrix_1.7-6       
## [13] data.table_1.18.4   RColorBrewer_1.1-3  S7_0.2.2           
## [16] desc_1.4.3          lifecycle_1.0.5     compiler_4.6.1     
## [19] farver_2.1.2        stringr_1.6.0       textshaping_1.0.5  
## [22] prettydoc_0.4.1     htmltools_0.5.9     sass_0.4.10        
## [25] yaml_2.3.12         plotly_4.12.1       pillar_1.11.1      
## [28] pkgdown_2.2.1       jquerylib_0.1.4     ellipsis_0.3.3     
## [31] DelayedArray_0.39.5 cachem_1.1.0        abind_1.4-8        
## [34] tidyselect_1.2.1    digest_0.6.39       stringi_1.8.9      
## [37] purrr_1.2.2         labeling_0.4.3      fastmap_1.2.0      
## [40] grid_4.6.1          cli_3.6.6           SparseArray_1.13.2 
## [43] magrittr_2.0.5      S4Arrays_1.13.0     utf8_1.2.6         
## [46] withr_3.0.3         scales_1.4.0        rmarkdown_2.31     
## [49] XVector_0.53.0      httr_1.4.8          otel_0.2.0         
## [52] ragg_1.5.2          evaluate_1.0.5      viridisLite_0.4.3  
## [55] rlang_1.3.0         glue_1.8.1          jsonlite_2.0.0     
## [58] R6_2.6.1            systemfonts_1.3.2   fs_2.1.0

References

Hutchison, William J, Timothy J Keyes, The tidyomics Consortium, et al. 2024. “The Tidyomics Ecosystem: Enhancing Omic Data Analyses.” Nature Methods 21 (8): 1166–70. https://doi.org/10.1038/s41592-024-02299-2.
Morgan, Martin, Valerie Obenchain, Jim Hester, and Hervé Pagès. 2020. SummarizedExperiment: SummarizedExperiment Container.
Wickham, Hadley, Mara Averick, Jennifer Bryan, et al. 2019. “Welcome to the Tidyverse.” Journal of Open Source Software 4 (43): 1686.