Skip to content

Commit 06c6132

Browse files
authored
Merge pull request #90 from noriakis/add-slice
Add slice functions
2 parents 77c9937 + 20fcdda commit 06c6132

File tree

7 files changed

+502
-2
lines changed

7 files changed

+502
-2
lines changed

NAMESPACE

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ S3method(sample_n,SingleCellExperiment)
3232
S3method(select,SingleCellExperiment)
3333
S3method(separate,SingleCellExperiment)
3434
S3method(slice,SingleCellExperiment)
35+
S3method(slice_head,SingleCellExperiment)
36+
S3method(slice_max,SingleCellExperiment)
37+
S3method(slice_min,SingleCellExperiment)
38+
S3method(slice_sample,SingleCellExperiment)
39+
S3method(slice_tail,SingleCellExperiment)
3540
S3method(summarise,SingleCellExperiment)
3641
S3method(summarize,SingleCellExperiment)
3742
S3method(tbl_format_header,tidySingleCellExperiment)
@@ -82,6 +87,11 @@ importFrom(dplyr,sample_frac)
8287
importFrom(dplyr,sample_n)
8388
importFrom(dplyr,select)
8489
importFrom(dplyr,slice)
90+
importFrom(dplyr,slice_head)
91+
importFrom(dplyr,slice_max)
92+
importFrom(dplyr,slice_min)
93+
importFrom(dplyr,slice_sample)
94+
importFrom(dplyr,slice_tail)
8595
importFrom(dplyr,summarise)
8696
importFrom(dplyr,summarize)
8797
importFrom(dplyr,vars)
@@ -111,6 +121,7 @@ importFrom(purrr,reduce)
111121
importFrom(purrr,when)
112122
importFrom(rlang,":=")
113123
importFrom(rlang,dots_values)
124+
importFrom(rlang,enexpr)
114125
importFrom(rlang,enquo)
115126
importFrom(rlang,enquos)
116127
importFrom(rlang,expr)
@@ -130,6 +141,7 @@ importFrom(stringr,str_replace_all)
130141
importFrom(tibble,as_tibble)
131142
importFrom(tibble,enframe)
132143
importFrom(tibble,glimpse)
144+
importFrom(tibble,rowid_to_column)
133145
importFrom(tidyr,extract)
134146
importFrom(tidyr,nest)
135147
importFrom(tidyr,pivot_longer)

R/dplyr_methods.R

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,188 @@ slice.SingleCellExperiment <- function(.data, ..., .by=NULL, .preserve=FALSE) {
507507
.data[, rownames(new_meta)]
508508
}
509509

510+
#' @name slice_sample
511+
#' @rdname slice
512+
#' @inherit dplyr::slice_sample
513+
#' @examples
514+
#' data(pbmc_small)
515+
#' pbmc_small |> slice_sample(n=1)
516+
#' pbmc_small |> slice_sample(prop=0.1)
517+
#'
518+
#' @importFrom SummarizedExperiment colData
519+
#' @importFrom dplyr slice_sample
520+
#' @export
521+
slice_sample.SingleCellExperiment <- function(.data, ..., n=NULL,
522+
prop=NULL, by=NULL, weight_by=NULL, replace=FALSE) {
523+
lifecycle::signal_superseded("1.0.0", "sample_n()", "slice_sample()")
524+
525+
if (!is.null(n))
526+
new_meta <-
527+
.data |>
528+
colData() |>
529+
as_tibble(rownames=c_(.data)$name) |>
530+
select(-everything(), c_(.data)$name, {{ by }}, {{ weight_by }}) |>
531+
slice_sample(..., n=n, by={{ by }},
532+
weight_by={{ weight_by }}, replace=replace)
533+
else if (!is.null(prop))
534+
new_meta <-
535+
.data |>
536+
colData() |>
537+
as_tibble(rownames=c_(.data)$name) |>
538+
select(-everything(), c_(.data)$name, {{ by }}, {{ weight_by }}) |>
539+
slice_sample(..., prop=prop, by={{ by }},
540+
weight_by={{ weight_by }}, replace=replace)
541+
else
542+
stop("tidySingleCellExperiment says:",
543+
" you should provide `n` or `prop` arguments")
544+
545+
count_cells <- new_meta %>%
546+
select(!!c_(.data)$symbol) %>%
547+
count(!!c_(.data)$symbol)
548+
549+
.max_cell_count <- ifelse(nrow(count_cells)==0, 0, max(count_cells$n))
550+
551+
# If repeated cells due to replacement
552+
if (.max_cell_count |> gt(1)){
553+
message("tidySingleCellExperiment says: When sampling with replacement",
554+
" a data frame is returned for independent data analysis.")
555+
.data |>
556+
as_tibble() |>
557+
right_join(new_meta %>%
558+
select(!!c_(.data)$symbol), by=c_(.data)$name)
559+
} else {
560+
.data[, pull(new_meta, !!c_(.data)$symbol)]
561+
}
562+
}
563+
564+
#' @name slice_head
565+
#' @rdname slice
566+
#' @inherit dplyr::slice_head
567+
#' @examples
568+
#' data(pbmc_small)
569+
#' # First rows based on existing order
570+
#' pbmc_small |> slice_head(n=5)
571+
#'
572+
#' @importFrom dplyr slice_head
573+
#' @importFrom tibble rowid_to_column
574+
#' @export
575+
slice_head.SingleCellExperiment <- function(.data, ..., n, prop, by=NULL) {
576+
row_number___ <- NULL
577+
idx <- .data |>
578+
colData() |>
579+
as.data.frame() |>
580+
select(-everything(), {{ by }}) |>
581+
rowid_to_column(var='row_number___') |>
582+
slice_head(..., n=n, prop=prop, by={{ by }}) |>
583+
pull(row_number___)
584+
585+
new_obj <- .data[, idx]
586+
new_obj
587+
}
588+
589+
#' @name slice_tail
590+
#' @rdname slice
591+
#' @inherit dplyr::slice_tail
592+
#' @examples
593+
#' data(pbmc_small)
594+
#' # First rows based on existing order
595+
#' pbmc_small |> slice_tail(n=5)
596+
#'
597+
#' @importFrom dplyr slice_tail
598+
#' @importFrom tibble rowid_to_column
599+
#' @export
600+
slice_tail.SingleCellExperiment <- function(.data, ..., n, prop, by=NULL) {
601+
row_number___ <- NULL
602+
idx <- .data |>
603+
colData() |>
604+
as.data.frame() |>
605+
select(-everything(), {{ by }}) |>
606+
rowid_to_column(var='row_number___') |>
607+
slice_tail(..., n=n, prop=prop, by={{ by }}) |>
608+
pull(row_number___)
609+
610+
new_obj <- .data[, idx]
611+
new_obj
612+
}
613+
614+
#' @name slice_min
615+
#' @rdname slice
616+
#' @inherit dplyr::slice_min
617+
#' @examples
618+
#' data(pbmc_small)
619+
#'
620+
#' # Rows with minimum and maximum values of a metadata variable
621+
#' pbmc_small |> slice_min(nFeature_RNA, n=5)
622+
#'
623+
#' # slice_min() and slice_max() may return more rows than requested
624+
#' # in the presence of ties.
625+
#' pbmc_small |> slice_min(nFeature_RNA, n=2)
626+
#'
627+
#' # Use with_ties=FALSE to return exactly n matches
628+
#' pbmc_small |> slice_min(nFeature_RNA, n=2, with_ties=FALSE)
629+
#'
630+
#' # Or use additional variables to break the tie:
631+
#' pbmc_small |> slice_min(tibble::tibble(nFeature_RNA, nCount_RNA), n=2)
632+
#'
633+
#' # Use by for group-wise operations
634+
#' pbmc_small |> slice_min(nFeature_RNA, n=5, by=groups)
635+
#'
636+
#' @importFrom dplyr slice_min
637+
#' @importFrom tibble rowid_to_column
638+
#' @export
639+
slice_min.SingleCellExperiment <- function(.data, order_by, ..., n, prop,
640+
by=NULL, with_ties=TRUE, na_rm=FALSE) {
641+
row_number___ <- NULL
642+
order_by_variables <- return_arguments_of(!!enexpr(order_by))
643+
644+
idx <- .data |>
645+
colData() |>
646+
as.data.frame() |>
647+
select(-everything(), !!!order_by_variables, {{ by }}) |>
648+
rowid_to_column(var ='row_number___') |>
649+
slice_min(
650+
order_by={{ order_by }}, ..., n=n, prop=prop, by={{ by }},
651+
with_ties=with_ties, na_rm=na_rm
652+
) |>
653+
pull(row_number___)
654+
655+
new_obj <- .data[, idx]
656+
new_obj
657+
}
658+
659+
#' @name slice_max
660+
#' @rdname slice
661+
#' @inherit dplyr::slice_max
662+
#' @examples
663+
#' data(pbmc_small)
664+
#' # Rows with minimum and maximum values of a metadata variable
665+
#' pbmc_small |> slice_max(nFeature_RNA, n=5)
666+
#'
667+
#' @importFrom dplyr slice_max
668+
#' @importFrom tibble rowid_to_column
669+
#' @export
670+
slice_max.SingleCellExperiment <- function(.data, order_by, ..., n, prop,
671+
by=NULL, with_ties=TRUE, na_rm=FALSE) {
672+
row_number___ <- NULL
673+
674+
order_by_variables <- return_arguments_of(!!enexpr(order_by))
675+
676+
idx <- .data |>
677+
colData() |>
678+
as.data.frame() |>
679+
select(-everything(), !!!order_by_variables, {{ by }}) |>
680+
rowid_to_column(var ='row_number___') |>
681+
slice_max(
682+
order_by={{ order_by }}, ..., n=n, prop=prop, by={{ by }},
683+
with_ties=with_ties, na_rm=na_rm
684+
) |>
685+
pull(row_number___)
686+
687+
new_obj <- .data[, idx]
688+
new_obj
689+
}
690+
691+
510692
#' @name select
511693
#' @rdname select
512694
#' @inherit dplyr::select

R/utilities.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,18 @@ quo_names <- function(v) {
306306
unlist()
307307
}
308308

309+
#' returns variables from an expression
310+
#' @param expression an expression
311+
#' @importFrom rlang enexpr
312+
#' @return list of symbols
313+
return_arguments_of <- function(expression){
314+
variables <- enexpr(expression) |> as.list()
315+
if(length(variables) > 1) {
316+
variables <- variables[-1] # removes first element which is function
317+
}
318+
variables
319+
}
320+
309321
#' @importFrom purrr when
310322
#' @importFrom dplyr select
311323
#' @importFrom rlang expr

man/bind_rows.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/return_arguments_of.Rd

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)