| Title: | DuckDB-Backed DelayedArray Implementation |
|---|---|
| Description: | Provides DuckDB-backed implementations of DelayedArray and DelayedMatrix classes for efficient, out-of-memory operations on large array and matrix datasets. The package includes DuckDBArray, DuckDBArraySeed, and DuckDBMatrix classes with optimized matrixStats methods. Supports sparse arrays, grid partitioning, and parallel processing for scalable genomic data analysis. |
| Authors: | Patrick Aboyoun [aut, cre], Genentech, Inc. [cph] |
| Maintainer: | Patrick Aboyoun <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.99.2 |
| Built: | 2026-07-23 11:10:39 UTC |
| Source: | https://github.com/BiocStaging/DuckDBArray |
Creates lookup tables for array dimensions that map dimension names to their corresponding indices and grid group identifiers. These tables are useful for understanding the structure of partitioned arrays and for reconstructing the original array from coordinate format data.
createDimTables( x, indexcols = names(dimnames(x)) %||% sprintf("index%d", seq_along(dim(x))), grid = defaultAutoGrid(COO_SparseArray(dim(x))), grid_suffix = "_group", BPPARAM = getAutoBPPARAM() )createDimTables( x, indexcols = names(dimnames(x)) %||% sprintf("index%d", seq_along(dim(x))), grid = defaultAutoGrid(COO_SparseArray(dim(x))), grid_suffix = "_group", BPPARAM = getAutoBPPARAM() )
x |
An array-like object with dimensions and dimension names. Must be
coercible to a |
indexcols |
A character vector of column names for the dimensions of the array. |
grid |
An optional ArrayGrid to use for partitioning
the array. If |
grid_suffix |
A character string to append to the partitioning directories if the grid contains more than one cell. Defaults to "_group". |
BPPARAM |
A BiocParallelParam object to use for
parallel processing when |
This function is particularly useful when working with partitioned arrays
created by writeCoordArray. The returned lookup tables provide a
mapping between dimension names and their positions in the original array,
as well as identify which grid partition contains each dimension element.
When the grid contains only one cell, the lookup tables contain only the dimension names and their indices. When multiple grid cells are present, additional columns indicate which grid group each dimension element belongs to.
A named list of data frames, one for each dimension in x.
Each data frame contains:
The dimension names as row names
A column with the corresponding indices
A column with the grid group identifier (if grid has multiple cells)
The list is named according to indexcols.
Patrick Aboyoun
writeCoordArray for writing arrays in coordinate format,
ArrayGrid for grid partitioning,
BiocParallelParam for parallel processing options
# Write the state.x77 matrix to multiple Parquet files using grid partitioning tf <- tempfile() state_grid <- RegularArrayGrid(dim(state.x77), c(10, 4)) writeCoordArray(state.x77, file.path(tf, "state"), grid = state_grid) dimtbls <- createDimTables(state.x77, grid = state_grid) list.files(tf, full.names = TRUE, recursive = TRUE)# Write the state.x77 matrix to multiple Parquet files using grid partitioning tf <- tempfile() state_grid <- RegularArrayGrid(dim(state.x77), c(10, 4)) writeCoordArray(state.x77, file.path(tf, "state"), grid = state_grid) dimtbls <- createDimTables(state.x77, grid = state_grid) list.files(tf, full.names = TRUE, recursive = TRUE)
The DuckDBArray class is a DelayedArray subclass for representing and operating on a DuckDB table.
All the operations available for DelayedArray objects work on DuckDBArray objects.
The DuckDBArray() constructor returns a DuckDBArray object.
The accessors return the component of x named by the accessor (e.g.
dim(x) returns an integer vector of the array dimensions).
DuckDBArray(conn, datacol, keycols, dimtbls = NULL, type = NULL):Creates a DuckDBArray object.
connEither a character vector containing the paths to parquet, csv, or
gzipped csv data files; a string that defines a duckdb read_*
data source; a DuckDBDataFrame object; or a tbl_duckdb_connection
object.
datacolEither a string specifying the column from conn or a named
expression that will be evaluated in the context of
conn that defines the values in the array.
keycolsEither a character vector of column names from conn that will
specify the dimension names, or a named list of character vectors
where the names of the list specify the dimension names and the
character vectors set the distinct values for the dimension names.
dimtblsEither NULL, a named DataFrameList object, or an environment
containing a named DataFrameList "dimtbls" element that
specifies the dimension tables associated with the keycols.
The name of the list elements match the names of the keycols
list. Additionally, the DataFrame objects have row names that
match the distinct values of the corresponding keycols list
element and columns that define partitions in the data table for
efficient querying.
typeString specifying the type of the data values; one of
"logical", "integer", "integer64",
"double", or "character". If NULL, it is
determined by inspecting the data.
In the code snippets below, x is a DuckDBArray object:
dim(x):An integer vector of the array dimensions.
dimnames(x), dimnames(x) <- value:Get or set the array dimension names.
dimtbls(x, drop = TRUE), dimtbls(x) <- value:Get or set the list of dimension tables used to define partitions for
efficient queries. If drop = TRUE, then it returns a named
DataFrameList object, else it returns an environment containing
a dimtbls named DataFrameList element.
type(x), type(x) <- value:Get or set the data type of the array elements; one of "logical",
"integer", "integer64", "double", or
"character".
In the code snippets below, x is a DuckDBArray object:
x[i, j, ..., drop = TRUE]:Returns a new DuckDBArray object. Empty dimensions are dropped if
drop = TRUE.
In the code snippets below, x is a DuckDBArray object:
aperm(a, perm):Returns a new DuckDBArray object with the dimensions permuted
according to the perm vector.
t(x):For two-dimensional arrays, returns a new DuckDBArray object with the dimensions transposed.
Patrick Aboyoun
DuckDBArray-utils for the utilities
DuckDBMatrix-class for the matrix class
DuckDBArraySeed-class for the internal seed class
DuckDBArraySeed-utils for the internal seed class
utilities
DelayedArray for the base class
# Create a data.frame from the Titanic data df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- Titanic[as.matrix(df)] # Write data to a parquet file tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqarray <- DuckDBArray(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived"))# Create a data.frame from the Titanic data df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- Titanic[as.matrix(df)] # Write data to a parquet file tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqarray <- DuckDBArray(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived"))
Row / column summarization methods for DuckDBArray objects.
Method return types are documented in the sections above.
In the code snippets below, x is a DuckDBArray object:
rowCounts(x, value = TRUE):Calculates the row counts of x that are equal to value.
valueThe value to count.
colCounts(x, value = TRUE):Calculates the column counts of x that are equal to value.
valueThe value to count.
rowMaxs(x):Calculates the row maxima of x.
colMaxs(x):Calculates the column maxima of x.
rowMeans(x, dims = 1):Calculates the row means of x.
dimsAn integer specifying which dimensions to average over,
namely dims + 1, ....
colMeans(x, dims = 1):Calculates the column means of x.
dimsAn integer specifying which dimensions to average over,
namely 1:dims.
rowMins(x):Calculates the row minima of x.
colMins(x):Calculates the column minima of x.
rowSums(x, dims = 1):Calculates the row sums of x.
dimsAn integer specifying which dimensions to sum over,
namely dims + 1, ....
colSums(x, dims = 1):Calculates the column sums of x.
dimsAn integer specifying which dimensions to sum over,
namely 1:dims.
rowSds(x):Calculates the row standard deviations of x.
colSds(x):Calculates the column standard deviations of x.
rowVars(x):Calculates the row variances of x.
colVars(x):Calculates the column variances of x.
Patrick Aboyoun
DuckDBArray-class for the main class
DuckDBMatrix-class for the matrix class
DuckDBArraySeed-class for the internal seed class
DuckDBArraySeed-matrixStats for the internal seed class
matrixStats methods
DelayedArray for the base class
df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqarray <- DuckDBArray(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived")) colMeans(pqarray) rowSums(pqarray, dims = 2L)df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqarray <- DuckDBArray(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived")) colMeans(pqarray) rowSums(pqarray, dims = 2L)
Common operations on DuckDBArray objects.
Method return types are documented in the sections above.
DuckDBArray objects have support for S4 group generic functionality:
Arith"+", "-", "*", "^",
"%%", "%/%", "/"
Compare"==", ">", "<", "!=",
"<=", ">="
Logic"&", "|", "!"
Ops"Arith", "Compare", "Logic"
Math"abs", "sign", "sqrt",
"ceiling", "floor", "trunc", "log",
"log10", "log2", "acos", "acosh",
"asin", "asinh", "atan", "atanh",
"exp", "expm1", "cos", "cosh",
"sin", "sinh", "tan", "tanh",
"gamma", "lgamma"
Summary"max", "min", "range",
"prod", "sum", "any", "all"
See S4groupGeneric for more details.
In the code snippets below, x is a DuckDBArray object:
is.finite(x):Returns a DuckDBArray containing logicals that indicate which values are finite.
is.infinite(x):Returns a DuckDBArray containing logicals that indicate which values are infinite.
is.nan(x):Returns a DuckDBArray containing logicals that indicate which values are Not a Number.
sweep(x, MARGIN, STATS, FUN = "/"):Sweeps out array summaries from x. Applies FUN to each
element of x using the corresponding value from STATS
based on MARGIN.
MARGINinteger specifying the dimension (1 for rows, 2 for columns)
STATSnumeric vector with length equal to the extent
of dimension MARGIN
FUNfunction to be used to carry out the sweep
In the code snippets below, x is a DuckDBArray object:
is_nonzero(x):Returns a DuckDBArray containing logicals that indicate if the values in
each of the columns of x are non-zero.
nzcount(x):Returns the total number of non-zero values.
nzvals(x):Returns the non-zero values.
is_sparse(x):Returns TRUE since data are stored in a sparse array representation.
Patrick Aboyoun
DuckDBArray-class for the main class
DuckDBMatrix-class for the matrix class
DuckDBArraySeed-class for the internal seed class
DuckDBArraySeed-utils for the internal seed class
utilities
DelayedArray for the base class
df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqarray <- DuckDBArray(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived")) is_sparse(pqarray) rowSums(pqarray) pqarray + 1Ldf <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqarray <- DuckDBArray(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived")) is_sparse(pqarray) rowSums(pqarray) pqarray + 1L
DuckDBArraySeed is a low-level helper class for representing a pointer to a DuckDB table.
Note that a DuckDBArraySeed object is not intended to be used directly.
Most end users will typically create and manipulate a higher-level
DuckDBArray object instead. See ?DuckDBArray for
more information.
The DuckDBArraySeed() constructor returns a DuckDBArraySeed
object; the accessors return the component of x named by the accessor.
DuckDBArraySeed(conn, datacol, keycols, dimtbls = NULL, type = NULL):Creates a DuckDBArraySeed object.
connEither a character vector containing the paths to parquet, csv, or
gzipped csv data files; a string that defines a duckdb read_*
data source; a DuckDBDataFrame object; or a tbl_duckdb_connection
object.
datacolEither a string specifying the column from conn or a named
expression that will be evaluated in the context of
conn that defines the values in the array.
keycolsEither a character vector of column names from conn that will
specify the dimension names, or a named list of character vectors
where the names of the list specify the dimension names and the
character vectors set the distinct values for the dimension names.
dimtblsEither NULL, a named DataFrameList object, or an environment
containing a named DataFrameList "dimtbls" element that
specifies the dimension tables associated with the keycols.
The name of the list elements match the names of the keycols
list. Additionally, the DataFrame objects have row names that
match the distinct values of the corresponding keycols list
element and columns that define partitions in the data table for
efficient querying.
typeString specifying the type of the data values; one of
"logical", "integer", "integer64",
"double", or "character". If NULL, it is
determined by inspecting the data.
In the code snippets below, x is a DuckDBArraySeed object:
dim(x):An integer vector of the array dimensions.
dimnames(x), dimnames(x) <- value:Get or set the array dimension names.
dimtbls(x, drop = TRUE), dimtbls(x) <- value:Get or set the list of dimension tables used to define partitions for
efficient queries. If drop = TRUE, then it returns a named
DataFrameList object, else it returns an environment containing
a dimtbls named DataFrameList element.
type(x), type(x) <- value:Get or set the data type of the array elements; one of "logical",
"integer", "integer64", "double", or
"character".
In the code snippets below, x is a DuckDBArraySeed object:
x[i, j, ..., drop = TRUE]:Returns a new DuckDBArraySeed object. Empty dimensions are dropped if
drop = TRUE.
In the code snippets below, x is a DuckDBArraySeed object:
aperm(a, perm):Returns a new DuckDBArraySeed object with the dimensions permuted
according to the perm vector.
t(x):For two-dimensional arrays, returns a new DuckDBArraySeed object with the dimensions transposed.
Patrick Aboyoun
DuckDBArraySeed-utils for the utilities
DuckDBArray-class for the main class
DuckDBArray-utils for the main class utilities
Array for the base class
# Create a data.frame from the Titanic data df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) # Write data to a parquet file tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqaseed <- DuckDBArraySeed(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived"))# Create a data.frame from the Titanic data df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) # Write data to a parquet file tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqaseed <- DuckDBArraySeed(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived"))
Row / column summarization methods for DuckDBArraySeed objects.
Method return types are documented in the sections above.
In the code snippets below, x is a DuckDBArraySeed object:
rowCounts(x, value = TRUE):Calculates the row counts of x that are equal to value.
valueThe value to count.
colCounts(x, value = TRUE):Calculates the column counts of x that are equal to value.
valueThe value to count.
rowMaxs(x):Calculates the row maxima of x.
colMaxs(x):Calculates the column maxima of x.
rowMeans(x, dims = 1):Calculates the row means of x.
dimsAn integer specifying which dimensions to average over,
namely dims + 1, ....
colMeans(x, dims = 1):Calculates the column means of x.
dimsAn integer specifying which dimensions to average over,
namely 1:dims.
rowMins(x):Calculates the row minima of x.
colMins(x):Calculates the column minima of x.
rowSums(x, dims = 1):Calculates the row sums of x.
dimsAn integer specifying which dimensions to sum over,
namely dims + 1, ....
colSums(x, dims = 1):Calculates the column sums of x.
dimsAn integer specifying which dimensions to sum over,
namely 1:dims.
rowSds(x):Calculates the row standard deviations of x.
colSds(x):Calculates the column standard deviations of x.
rowVars(x):Calculates the row variances of x.
colVars(x):Calculates the column variances of x.
Patrick Aboyoun
DuckDBArraySeed-class for the internal seed class
DuckDBArray-class for the main class
DuckDBArray-matrixStats for the main class matrixStats methods
Array for the base class
df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) seed <- DuckDBArraySeed(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived")) colMeans(seed) rowSums(seed, dims = 2L)df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) seed <- DuckDBArraySeed(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived")) colMeans(seed) rowSums(seed, dims = 2L)
Common operations on DuckDBArraySeed objects.
Method return types are documented in the sections above.
DuckDBArraySeed objects have support for S4 group generic functionality:
Arith"+", "-", "*", "^",
"%%", "%/%", "/"
Compare"==", ">", "<", "!=",
"<=", ">="
Logic"&", "|", "!"
Ops"Arith", "Compare", "Logic"
Math"abs", "sign", "sqrt",
"ceiling", "floor", "trunc", "log",
"log10", "log2", "acos", "acosh",
"asin", "asinh", "atan", "atanh",
"exp", "expm1", "cos", "cosh",
"sin", "sinh", "tan", "tanh",
"gamma", "lgamma"
Summary"max", "min", "range",
"prod", "sum", "any", "all"
See S4groupGeneric for more details.
In the code snippets below, x is a DuckDBArraySeed object:
is.finite(x):Returns a DuckDBArraySeed containing logicals that indicate which values are finite.
is.infinite(x):Returns a DuckDBArraySeed containing logicals that indicate which values are infinite.
is.nan(x):Returns a DuckDBArraySeed containing logicals that indicate which values are Not a Number.
sweep(x, MARGIN, STATS, FUN = "/"):Sweeps out array summaries from x. Applies FUN to each
element of x using the corresponding value from STATS
based on MARGIN.
MARGINinteger specifying the dimension (1 for rows, 2 for columns)
STATSnumeric vector with length equal to the extent
of dimension MARGIN
FUNfunction to be used to carry out the sweep
In the code snippets below, x is a DuckDBArraySeed object:
is_nonzero(x):Returns a DuckDBArraySeed containing logicals that indicate if the
values in each of the columns of x are non-zero.
nzcount(x):Returns the total number of non-zero values.
is_sparse(x):Returns TRUE since data are stored in a sparse array representation.
Patrick Aboyoun
DuckDBArraySeed-class for the internal seed class
DuckDBArray-class for the main class
DuckDBArray-utils for the main class utilities
Array for the base class
df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) seed <- DuckDBArraySeed(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived")) is_sparse(seed) nzcount(seed) seed + 1Ldf <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) seed <- DuckDBArraySeed(tf, datacol = "fate", keycols = c("Class", "Sex", "Age", "Survived")) is_sparse(seed) nzcount(seed) seed + 1L
The DuckDBMatrix class is a DelayedMatrix subclass for representing and operating on a DuckDB table.
All the operations available for DelayedMatrix objects work on DuckDBMatrix objects.
The DuckDBMatrix() constructor returns a DuckDBMatrix object;
the accessors return the component of x named by the accessor.
DuckDBMatrix(conn, datacol, row, col, keycols = c(row, col), dimtbls = NULL, type = NULL):Creates a DuckDBMatrix object.
connEither a character vector containing the paths to parquet, csv, or
gzipped csv data files; a string that defines a duckdb read_*
data source; a DuckDBDataFrame object; or a tbl_duckdb_connection
object.
datacolEither a string specifying the column from conn or a named
expression that will be evaluated in the context of
conn that defines the values in the matrix.
rowEither a string that specifies the column in conn that
specifies the row names of the matrix, or a named list containing a
single character vector that defines the column in conn for
the row names and its values.
colEither a string that specifies the column in conn that
specifies the column names of the matrix, or a named list containing
a single character vector that defines the column in conn for
the column names and its values.
keycolsAn optional character vector that define the names of the columns in
conn for the rows and columns of the matrix, or a named list
of character vectors where the names of the list define rows and
columns and the character vectors define distinct values for the rows
and columns.
dimtblsEither NULL, a named DataFrameList object, or an environment
containing a named DataFrameList "dimtbls" element that
specifies the dimension tables associated with the keycols.
The name of the list elements match the names of the keycols
list. Additionally, the DataFrame objects have row names that
match the distinct values of the corresponding keycols list
element and columns that define partitions in the data table for
efficient querying.
typeString specifying the type of the data values; one of
"logical", "integer", "integer64",
"double", or "character". If NULL, it is
determined by inspecting the data.
In the code snippets below, x is a DuckDBMatrix object:
dim(x):An integer vector of the array dimensions.
dimnames(x), dimnames(x) <- value:Get or set the array dimension names.
dimtbls(x, drop = TRUE), dimtbls(x) <- value:Get or set the list of dimension tables used to define partitions for
efficient queries. If drop = TRUE, then it returns a named
DataFrameList object, else it returns an environment containing
a dimtbls named DataFrameList element.
type(x), type(x) <- value:Get or set the data type of the array elements; one of "logical",
"integer", "integer64", "double", or
"character".
In the code snippets below, x is a DuckDBMatrix object:
x[i, j, ..., drop = TRUE]:Returns a new DuckDBMatrix object. Empty dimensions are dropped if
drop = TRUE.
In the code snippets below, x is a DuckDBMatrix object:
aperm(a, perm):Returns a new DuckDBMatrix object with the dimensions permuted
according to the perm vector.
t(x):Returns a new DuckDBMatrix object with the rows and columns transposed.
Patrick Aboyoun
DuckDBArray-class for the array class
DuckDBArray-utils for the array utilities
DuckDBArraySeed-class for the internal seed class
DuckDBArraySeed-utils for the internal seed class
utilities
DelayedMatrix for the base class
# Create a data.frame from a matrix df <- data.frame( rowname = rep(rownames(state.x77), times = ncol(state.x77)), colname = rep(colnames(state.x77), each = nrow(state.x77)), value = as.vector(state.x77) ) # Write data to a parquet file tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqmat <- DuckDBMatrix(tf, row = "rowname", col = "colname", datacol = "value")# Create a data.frame from a matrix df <- data.frame( rowname = rep(rownames(state.x77), times = ncol(state.x77)), colname = rep(colnames(state.x77), each = nrow(state.x77)), value = as.vector(state.x77) ) # Write data to a parquet file tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) pqmat <- DuckDBMatrix(tf, row = "rowname", col = "colname", datacol = "value")
Matrix multiplication methods for DuckDBMatrix objects.
Method return types are documented in the sections above.
In the code snippets below, x is a DuckDBMatrix object and y
is an ordinary matrix or vector:
x %*% y:Matrix multiplication via SQL aggregation.
crossprod(x, y):Cross-product, equivalent to t(x) %*% y.
tcrossprod(x, y):Transposed cross-product, equivalent to x %*% t(y).
crossprod(x):Self cross-product via SQL self-join.
tcrossprod(x):Self transposed cross-product via SQL self-join.
Patrick Aboyoun
DuckDBMatrix-class for the main class
DuckDBArray-utils for array utilities
state_df <- data.frame( index1 = rep(rownames(state.x77), times = ncol(state.x77)), index2 = rep(colnames(state.x77), each = nrow(state.x77)), value = as.vector(state.x77) ) state_df <- subset(state_df, value != 0) tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(state_df, tf) pqmat <- DuckDBMatrix(tf, datacol = "value", keycols = list(index1 = rownames(state.x77), index2 = colnames(state.x77))) y <- rep(1, ncol(pqmat)) pqmat %*% y dim(crossprod(pqmat))state_df <- data.frame( index1 = rep(rownames(state.x77), times = ncol(state.x77)), index2 = rep(colnames(state.x77), each = nrow(state.x77)), value = as.vector(state.x77) ) state_df <- subset(state_df, value != 0) tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(state_df, tf) pqmat <- DuckDBMatrix(tf, datacol = "value", keycols = list(index1 = rownames(state.x77), index2 = colnames(state.x77))) y <- rep(1, ncol(pqmat)) pqmat %*% y dim(crossprod(pqmat))
Row / column summarization methods for DuckDBTable objects.
Method return types are documented in the sections above.
In the code snippets below, x is a DuckDBTable object:
rowCounts(x, value = TRUE):Calculates the row counts of x that are equal to value.
valueThe value to count.
colCounts(x, value = TRUE):Calculates the column counts of x that are equal to value.
valueThe value to count.
rowMaxs(x):Calculates the row maxima of x.
colMaxs(x):Calculates the column maxima of x.
rowMeans(x, dims = 1):Calculates the row means of x.
dimsAn integer specifying which dimensions to average over,
namely dims + 1, ....
colMeans(x, dims = 1):Calculates the column means of x.
dimsAn integer specifying which dimensions to average over,
namely 1:dims.
rowMins(x):Calculates the row minima of x.
colMins(x):Calculates the column minima of x.
rowSums(x, dims = 1):Calculates the row sums of x.
dimsAn integer specifying which dimensions to sum over,
namely dims + 1, ....
colSums(x, dims = 1):Calculates the column sums of x.
dimsAn integer specifying which dimensions to sum over,
namely 1:dims.
rowSds(x):Calculates the row standard deviations of x.
colSds(x):Calculates the column standard deviations of x.
rowVars(x):Calculates the row variances of x.
colVars(x):Calculates the column variances of x.
In the code snippets below, x is a DuckDBTable object:
sweep(x, MARGIN, STATS, FUN = "/"):Sweeps out array summaries from x. Applies FUN to each
element of x using the corresponding value from STATS
based on MARGIN.
MARGINinteger specifying the dimension (1 for rows, 2 for columns)
STATSnumeric vector with length equal to the extent
of dimension MARGIN
FUNfunction to be used to carry out the sweep
Patrick Aboyoun
DuckDBTable-class for the main class
RectangularData for the base class
df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) tbl <- DuckDBTable(tf, datacols = "fate", keycols = c("Class", "Sex", "Age", "Survived")) rowSums(tbl) colMeans(tbl)df <- do.call(expand.grid, c(dimnames(Titanic), stringsAsFactors = FALSE)) df$fate <- as.integer(Titanic[as.matrix(df)]) df <- df[df$fate != 0L, ] tf <- tempfile(fileext = ".parquet") on.exit(unlink(tf)) arrow::write_parquet(df, tf) tbl <- DuckDBTable(tf, datacols = "fate", keycols = c("Class", "Sex", "Age", "Survived")) rowSums(tbl) colMeans(tbl)
Compute per-row (per-gene) deviance statistics for feature selection in single-cell RNA-seq data. Genes with high deviance are likely to be informative for downstream analysis.
rowDeviances(x, family = c("binomial", "poisson"), ...) ## S4 method for signature 'matrix' rowDeviances(x, family = c("binomial", "poisson"), ...) ## S4 method for signature 'dgCMatrix' rowDeviances(x, family = c("binomial", "poisson"), ...) ## S4 method for signature 'DelayedMatrix' rowDeviances( x, family = c("binomial", "poisson"), ..., grid = NULL, as.sparse = NA, BPPARAM = getAutoBPPARAM() ) ## S4 method for signature 'DuckDBMatrix' rowDeviances(x, family = c("binomial", "poisson"), ...)rowDeviances(x, family = c("binomial", "poisson"), ...) ## S4 method for signature 'matrix' rowDeviances(x, family = c("binomial", "poisson"), ...) ## S4 method for signature 'dgCMatrix' rowDeviances(x, family = c("binomial", "poisson"), ...) ## S4 method for signature 'DelayedMatrix' rowDeviances( x, family = c("binomial", "poisson"), ..., grid = NULL, as.sparse = NA, BPPARAM = getAutoBPPARAM() ) ## S4 method for signature 'DuckDBMatrix' rowDeviances(x, family = c("binomial", "poisson"), ...)
x |
A matrix-like object with genes in rows and cells in columns. Typically a count matrix (not log-transformed). |
family |
Character string specifying the null model distribution.
Either |
... |
Additional arguments (currently unused). |
grid |
For |
as.sparse |
For |
BPPARAM |
For |
The deviance statistic measures how poorly each gene fits a simple null model where expression is constant across cells (after accounting for library size). Genes with high deviance show more variation than expected under the null model and are good candidates for highly variable gene selection.
For family = "binomial", the null model treats each UMI as a
Bernoulli trial with gene-specific success probability. This is the
closest approximation to multinomial sampling.
For family = "poisson", the null model assumes Poisson-distributed
counts with rate proportional to library size. This is faster to compute
and often gives similar results to binomial.
A numeric vector of deviance statistics, one per row of x.
Names are preserved from rownames(x) if present.
Patrick Aboyoun
Townes FW, Hicks SC, Aryee MJ, and Irizarry RA (2019). Feature Selection and Dimension Reduction for Single Cell RNA-Seq based on a Multinomial Model. Genome Biology https://doi.org/10.1186/s13059-019-1861-6
rowVars for variance-based feature selection.
# Generate example count data set.seed(123) mat <- matrix(rpois(1000, lambda = 5), nrow = 100, ncol = 10) rownames(mat) <- paste0("Gene", 1:100) # Compute deviances dev_binom <- rowDeviances(mat, family = "binomial") dev_pois <- rowDeviances(mat, family = "poisson") # Select top variable genes top_genes <- head(order(dev_binom, decreasing = TRUE), 20)# Generate example count data set.seed(123) mat <- matrix(rpois(1000, lambda = 5), nrow = 100, ncol = 10) rownames(mat) <- paste0("Gene", 1:100) # Compute deviances dev_binom <- rowDeviances(mat, family = "binomial") dev_pois <- rowDeviances(mat, family = "poisson") # Select top variable genes top_genes <- head(order(dev_binom, decreasing = TRUE), 20)
Count the number of non-zero elements per row or column of a matrix-like object. This is useful for filtering genes by detection rate (number of cells where the gene is expressed) or filtering cells by complexity (number of genes detected).
rowNnzs(x, value = vector(type(x), 1L), ...) colNnzs(x, value = vector(type(x), 1L), ...) ## S4 method for signature 'ANY' rowNnzs(x, value = vector(type(x), 1L), ...) ## S4 method for signature 'DuckDBArray' rowNnzs( x, value = vector(type(x), 1L), na.rm = FALSE, dims = 1, ..., useNames = TRUE ) ## S4 method for signature 'ANY' colNnzs(x, value = vector(type(x), 1L), ...) ## S4 method for signature 'DuckDBArray' colNnzs( x, value = vector(type(x), 1L), na.rm = FALSE, dims = 1, ..., useNames = TRUE )rowNnzs(x, value = vector(type(x), 1L), ...) colNnzs(x, value = vector(type(x), 1L), ...) ## S4 method for signature 'ANY' rowNnzs(x, value = vector(type(x), 1L), ...) ## S4 method for signature 'DuckDBArray' rowNnzs( x, value = vector(type(x), 1L), na.rm = FALSE, dims = 1, ..., useNames = TRUE ) ## S4 method for signature 'ANY' colNnzs(x, value = vector(type(x), 1L), ...) ## S4 method for signature 'DuckDBArray' colNnzs( x, value = vector(type(x), 1L), na.rm = FALSE, dims = 1, ..., useNames = TRUE )
x |
A matrix-like object. |
value |
The value to treat as "zero" (i.e., elements NOT equal to this
value are counted). Defaults to the zero value for the storage mode of
|
... |
|
na.rm |
If |
dims |
A single integer specifying the dimension(s) over which to
operate. For |
useNames |
If |
These functions are convenience wrappers around rowCounts and
colCounts that count elements not equal to zero. The zero value
is determined by the storage mode of x:
For logical matrices: FALSE
For integer matrices: 0L
For numeric matrices: 0
For character matrices: ""
An integer vector with length equal to nrow(x) for
rowNnzs or ncol(x) for colNnzs.
Patrick Aboyoun
rowCounts for counting specific values.
# Dense matrix mat <- matrix(c(0L, 1L, 2L, 0L, 0L, 3L), nrow = 2) rowNnzs(mat) colNnzs(mat)# Dense matrix mat <- matrix(c(0L, 1L, 2L, 0L, 0L, 3L), nrow = 2) rowNnzs(mat) colNnzs(mat)
An arrow::write_dataset wrapper function to write array-like objects
in coordinate format. If dimension names are present, they are substituted
for the corresponding indices.
writeCoordArray( x, path, indexcols = names(dimnames(x)) %||% sprintf("index%d", seq_along(dim(x))), datacol = "value", grid = defaultAutoGrid(COO_SparseArray(dim(x))), grid_suffix = "_group", arrowtype = NULL, max_dim = NULL, append = FALSE, along = NULL, offset = 0L, group_offset = 0L, ... ) ## S4 method for signature 'ANY' writeCoordArray( x, path, indexcols = names(dimnames(x)) %||% sprintf("index%d", seq_along(dim(x))), datacol = "value", grid = defaultAutoGrid(COO_SparseArray(dim(x))), grid_suffix = "_group", arrowtype = NULL, max_dim = NULL, append = FALSE, along = NULL, offset = 0L, group_offset = 0L, BPPARAM = getAutoBPPARAM(), ... ) ## S4 method for signature 'DuckDBArray' writeCoordArray( x, path, indexcols = names(dimnames(x)) %||% sprintf("index%d", seq_along(dim(x))), datacol = "value", grid = defaultAutoGrid(COO_SparseArray(dim(x))), grid_suffix = "_group", arrowtype = NULL, max_dim = NULL, append = FALSE, along = NULL, offset = 0L, group_offset = 0L, ... )writeCoordArray( x, path, indexcols = names(dimnames(x)) %||% sprintf("index%d", seq_along(dim(x))), datacol = "value", grid = defaultAutoGrid(COO_SparseArray(dim(x))), grid_suffix = "_group", arrowtype = NULL, max_dim = NULL, append = FALSE, along = NULL, offset = 0L, group_offset = 0L, ... ) ## S4 method for signature 'ANY' writeCoordArray( x, path, indexcols = names(dimnames(x)) %||% sprintf("index%d", seq_along(dim(x))), datacol = "value", grid = defaultAutoGrid(COO_SparseArray(dim(x))), grid_suffix = "_group", arrowtype = NULL, max_dim = NULL, append = FALSE, along = NULL, offset = 0L, group_offset = 0L, BPPARAM = getAutoBPPARAM(), ... ) ## S4 method for signature 'DuckDBArray' writeCoordArray( x, path, indexcols = names(dimnames(x)) %||% sprintf("index%d", seq_along(dim(x))), datacol = "value", grid = defaultAutoGrid(COO_SparseArray(dim(x))), grid_suffix = "_group", arrowtype = NULL, max_dim = NULL, append = FALSE, along = NULL, offset = 0L, group_offset = 0L, ... )
x |
An array-like object. |
path |
The path to write the array-like object to. |
indexcols |
A character vector of column names for the dimensions of the array. |
datacol |
A character string specifying the column name containing the array values in the resulting table. Defaults to "value". |
grid |
An optional ArrayGrid to use for partitioning
the array. If |
grid_suffix |
A character string to append to the partitioning directories if the grid contains more than one cell. Defaults to "_group". |
arrowtype |
An optional DataType for the value column
(e.g. |
max_dim |
Optional integer vector of length |
append |
Logical; when
Because arrow's dataset reader requires a uniform schema across files,
these checks make silent schema drift and silent partition collisions
impossible. Defaults to |
along |
Integer index of the dimension along which to append new
partitions. Required when |
offset |
Non-negative integer added to the coordinates in dimension
|
group_offset |
Non-negative integer added to the partition group
index along dimension |
... |
Additional arguments to pass to |
BPPARAM |
A BiocParallelParam object to use for
parallel processing when |
Called for its side effect of writing x to path as
coordinate-format Parquet; returns NULL invisibly.
Patrick Aboyoun
# Write the state.x77 matrix to multiple Parquet files using grid partitioning tf <- tempfile() state_grid <- RegularArrayGrid(dim(state.x77), c(10, 4)) writeCoordArray(state.x77, file.path(tf, "state"), grid = state_grid) list.files(tf, full.names = TRUE, recursive = TRUE) # Append mode: write two column-slabs as distinct hive partitions without # first materializing cbind(slab1, slab2). Omitting 'arrowtype' and # 'max_dim' is safe -- both are read from the existing schema so the # appended slab is guaranteed to match. tf2 <- tempfile() slab1 <- state.x77[, 1:4] slab2 <- state.x77[, 5:8] grid1 <- RegularArrayGrid(dim(slab1), c(10L, 2L)) # 2 col partitions grid2 <- RegularArrayGrid(dim(slab2), c(10L, 2L)) # 2 more col partitions writeCoordArray(slab1, file.path(tf2, "state"), grid = grid1) writeCoordArray(slab2, file.path(tf2, "state"), grid = grid2, append = TRUE, along = 2L, offset = ncol(slab1), group_offset = dim(grid1)[2L]) # Pinning 'arrowtype' / 'max_dim' is still useful when the first slab's # inferred schema is narrower than you want the final dataset to have # (e.g. a small first slab that picks uint8 but you know later slabs # will need uint16). Pin both on every call for a fully-predictable # dataset schema. tf3 <- tempfile() int_slab <- state.x77[, c("Population", "Income")] float_slab <- state.x77[, c("Illiteracy", "Life Exp")] grid_i <- RegularArrayGrid(dim(int_slab), c(10L, 2L)) grid_f <- RegularArrayGrid(dim(float_slab), c(10L, 2L)) max_dim <- c(nrow(state.x77), ncol(state.x77)) writeCoordArray(int_slab, file.path(tf3, "state"), grid = grid_i, arrowtype = arrow::float64(), max_dim = max_dim) writeCoordArray(float_slab, file.path(tf3, "state"), grid = grid_f, arrowtype = arrow::float64(), max_dim = max_dim, append = TRUE, along = 2L, offset = ncol(int_slab), group_offset = dim(grid_i)[2L])# Write the state.x77 matrix to multiple Parquet files using grid partitioning tf <- tempfile() state_grid <- RegularArrayGrid(dim(state.x77), c(10, 4)) writeCoordArray(state.x77, file.path(tf, "state"), grid = state_grid) list.files(tf, full.names = TRUE, recursive = TRUE) # Append mode: write two column-slabs as distinct hive partitions without # first materializing cbind(slab1, slab2). Omitting 'arrowtype' and # 'max_dim' is safe -- both are read from the existing schema so the # appended slab is guaranteed to match. tf2 <- tempfile() slab1 <- state.x77[, 1:4] slab2 <- state.x77[, 5:8] grid1 <- RegularArrayGrid(dim(slab1), c(10L, 2L)) # 2 col partitions grid2 <- RegularArrayGrid(dim(slab2), c(10L, 2L)) # 2 more col partitions writeCoordArray(slab1, file.path(tf2, "state"), grid = grid1) writeCoordArray(slab2, file.path(tf2, "state"), grid = grid2, append = TRUE, along = 2L, offset = ncol(slab1), group_offset = dim(grid1)[2L]) # Pinning 'arrowtype' / 'max_dim' is still useful when the first slab's # inferred schema is narrower than you want the final dataset to have # (e.g. a small first slab that picks uint8 but you know later slabs # will need uint16). Pin both on every call for a fully-predictable # dataset schema. tf3 <- tempfile() int_slab <- state.x77[, c("Population", "Income")] float_slab <- state.x77[, c("Illiteracy", "Life Exp")] grid_i <- RegularArrayGrid(dim(int_slab), c(10L, 2L)) grid_f <- RegularArrayGrid(dim(float_slab), c(10L, 2L)) max_dim <- c(nrow(state.x77), ncol(state.x77)) writeCoordArray(int_slab, file.path(tf3, "state"), grid = grid_i, arrowtype = arrow::float64(), max_dim = max_dim) writeCoordArray(float_slab, file.path(tf3, "state"), grid = grid_f, arrowtype = arrow::float64(), max_dim = max_dim, append = TRUE, along = 2L, offset = ncol(int_slab), group_offset = dim(grid_i)[2L])