Convert a SingleCellExperiment assay to a scipy CSC sparse matrix
sce_assay_to_scipy_csc.RdExtracts an assay from a SingleCellExperiment::SingleCellExperiment object,
coerces it to a Matrix::dgCMatrix, and constructs a Python
scipy.sparse.csc_matrix by passing reticulate::np_array() views of the
underlying R memory (true zero-copy: flags.owndata = FALSE).
Slot mapping
R (dgCMatrix) | Python / scipy CSC | dtype |
x@x | data | float64 |
x@i | indices | int32 |
x@p | indptr | int32 |
x@Dim | shape | – |
Zero-copy semantics
reticulate::np_array() uses the C buffer protocol to expose R's
contiguous memory to NumPy without copying (flags.owndata = FALSE).
This works because plain R vectors are already C-contiguous:
R numeric (
double) maps directly to NumPyfloat64.R integer (
int32_t) maps directly to NumPyint32.
Note on np.array(..., copy=False): NumPy >= 2.0 changed this flag to
raise ValueError when a copy would be needed. Using
reticulate::np_array() avoids this entirely and is the canonical
reticulate API for zero-copy array creation from R.
Lifetime caveat: the returned Python object holds a borrowed reference
to the underlying R vectors. Do not modify, reallocate, or allow the
mat@x, mat@i, mat@p vectors to be garbage-collected while the Python
object is alive.
Examples
if (FALSE) { # \dontrun{
library(SingleCellExperiment)
library(Matrix)
counts <- rsparsematrix(200, 50, density = 0.1, repr = "C")
sce <- SingleCellExperiment(assays = list(counts = counts))
csc <- sce_assay_to_scipy_csc(sce, assay = "counts")
sp <- reticulate::import("scipy.sparse", convert = FALSE)
shape_r <- reticulate::py_to_r(csc$shape)
cat("Shape:", shape_r[[1]], "x", shape_r[[2]], "\n")
cat("Sparse:", reticulate::py_to_r(sp$issparse(csc)), "\n")
cat("owndata:", reticulate::py_to_r(csc$data$flags$owndata), "\n")
} # }