如何找到不包括 0 值的稀疏矩阵的列均值?
How to find the column means for a sparse matrix excluding 0 values?
我有一个结构类似于此的稀疏矩阵,但要大得多。
library(Matrix)
dfmtest<-new("dgCMatrix"
, i = c(0L, 1L, 2L, 4L, 5L, 6L, 8L, 0L, 1L, 2L, 3L, 4L, 6L, 7L, 8L,
0L, 2L, 3L, 6L, 7L, 8L, 1L, 2L, 4L, 5L, 6L, 7L, 8L, 9L, 0L, 1L,
3L, 4L, 5L, 6L, 7L, 8L, 9L, 0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L,
9L, 0L, 1L, 3L, 4L, 6L, 7L, 8L, 9L, 0L, 2L, 3L, 5L, 6L, 7L, 9L,
0L, 1L, 2L, 3L, 4L, 5L, 6L, 8L, 9L, 0L, 1L, 2L, 3L, 4L, 5L, 6L,
7L, 9L)
, p = c(0L, 7L, 15L, 21L, 29L, 38L, 48L, 56L, 63L, 72L, 81L)
, Dim = c(10L, 10L)
, Dimnames = list(NULL, NULL)
, x = c(4, 3, 1, 2, 3, 1, 2, 1, 3, 3, 2, 3, 3, 3, 4, 2, 1, 2, 3, 2,
1, 4, 1, 2, 2, 3, 2, 3, 4, 1, 4, 1, 3, 4, 3, 2, 2, 2, 4, 1, 2,
2, 1, 2, 3, 1, 1, 1, 4, 1, 1, 2, 1, 1, 1, 4, 3, 3, 2, 1, 2, 2,
1, 1, 3, 3, 4, 1, 2, 4, 2, 4, 1, 2, 2, 3, 4, 2, 1, 2, 4)
, factors = list()
)
我希望能够找到每列(最后是行)的平均值,不包括 0 值。如果我尝试手动执行此操作,由于我的稀疏矩阵的大小,我 运行 会遇到内存问题。
nzmean <- function(x) {
mean(x[x!=0])
}
dfmmeans <- apply(dfmtest, 2, nzmean)
# 1 2 3 4 5 6 7 8
#2.285714 2.750000 1.833333 2.625000 2.444444 1.800000 1.875000 2.000000
# 9 10
#2.666667 2.333333
当我在我的实际矩阵上 运行 以上时,我得到以下错误:
Error in asMethod(object) :
Cholmod error 'problem too large' at file ../Core/cholmod_dense.c, line 105
我也研究过使用 colMeans
函数,但它看起来好像在计算中包含所有 0 值。
dfmmeans <- colMeans(dfmtest)
#[1] 1.6 2.2 1.1 2.1 2.2 1.8 1.5 1.4 2.4 2.1
有没有在大型稀疏矩阵上执行此操作的好方法?
确实colMeans
不支持删除零:
getMethod("colMeans", "dgCMatrix")
#Method Definition:
#
#function (x, na.rm = FALSE, dims = 1, ...)
#{
# .local <- function (x, na.rm = FALSE, dims = 1, sparseResult = FALSE)
# .Call(dgCMatrix_colSums, x, na.rm, sparseResult, FALSE, TRUE)
# .local(x, na.rm, dims, ...)
#}
#<environment: namespace:Matrix>
所以我们需要制定自己的功能。
colMeans_drop0 <- function (dgCMat) {
nnz_per_col <- diff(dgCMat@p)
ColInd <- rep.int(1:ncol(dgCMat), nnz_per_col)
sapply(split(dgCMat@x, ColInd), mean)
}
colMeans_drop0(dfmtest)
# 1 2 3 4 5 6 7 8
#2.285714 2.750000 1.833333 2.625000 2.444444 1.800000 1.875000 2.000000
# 9 10
#2.666667 2.333333
注意:全为零的列将被忽略。同样:
rowMeans_drop0 <- function (dgCMat) {
RowInd <- dgCMat@i + 1
sapply(split(dgCMat@x, RowInd), mean)
}
所有零的行都将被忽略。
备注
也不错
summary
+ aggregate
方法是此答案中想法的不同实现方式。
getMethod("summary", "sparseMatrix")
#Method Definition:
#
#function (object, ...)
#{
# d <- dim(object)
# T <- as(object, "TsparseMatrix")
# r <- if (is(object, "nsparseMatrix"))
# data.frame(i = T@i + 1L, j = T@j + 1L)
# else data.frame(i = T@i + 1L, j = T@j + 1L, x = T@x)
# attr(r, "header") <- sprintf("%d x %d sparse Matrix of class \"%s\", with %d entries",
# d[1], d[2], class(object), length(T@i))
# class(r) <- c("sparseSummary", class(r))
# r
#}
#<environment: namespace:Matrix>
summary
首先将任何稀疏矩阵 class 强制转换为 "dgTMatrix"
class,即 三元组格式 ,然后aggregate
内部依赖于 split
+ lapply
。
如果您想保留全零列的结果(当然是 0),使用 colSums
的想法可能是可取的。
的讨论
我们的功能也可以基于 colSums
/ rowSums
实现。
colMeans_drop0 <- function (dgCMat) {
nnz_per_col <- diff(dgCMat@p)
nnz_per_col[nnz_per_col == 0] <- 1 ## just avoid doing 0 / 0
setNames(colSums(dgCMat) / nnz_per_col, 1:ncol(dgCMat))
}
rowMeans_drop0 <- function (dgCMat) {
RowInd <- dgCMat@i + 1
nnz_per_row <- tabulate(RowInd)
nnz_per_row[nnz_per_row == 0] <- 1 ## just avoid doing 0 / 0
setNames(rowSums(dgCMat) / nnz_per_row, 1:nrow(dgCMat))
}
由于 colSums
/ rowSums
删除了 dimnames,我们将它们添加到 setNames
中。这两个函数保留全零列/行的结果。我们还使用 tabulate
函数来有效地计算行中非零条目的数量。
我们可以直接使用tapply
tapply(dfmtest@x,col(dfmtest)[(!dfmtest==0)@x],mean)
1 2 3 4 5 6 7 8 9 10
2.285714 2.750000 1.833333 2.625000 2.444444 1.800000 1.875000 2.000000 2.666667 2.333333
或者你可以
Matrix 有一个很好的 summary
方法,即 returns 矩阵中非零元素的 i、j、x 数据框,可以使用 aggregate
轻松总结(或者 dplyr 或 data.table,如果你愿意的话):
library(Matrix)
str(summary(dfmtest))
#> Classes 'sparseSummary' and 'data.frame': 81 obs. of 3 variables:
#> $ i: int 1 2 3 5 6 7 9 1 2 3 ...
#> $ j: int 1 1 1 1 1 1 1 2 2 2 ...
#> $ x: num 4 3 1 2 3 1 2 1 3 3 ...
#> - attr(*, "header")= chr "10 x 10 sparse Matrix of class \"dgCMatrix\", with 81 entries"
aggregate(x ~ j, summary(dfmtest), mean)
#> j x
#> 1 1 2.285714
#> 2 2 2.750000
#> 3 3 1.833333
#> 4 4 2.625000
#> 5 5 2.444444
#> 6 6 1.800000
#> 7 7 1.875000
#> 8 8 2.000000
#> 9 9 2.666667
#> 10 10 2.333333
如果您想要纯矩阵操作版本,可以使用 abs(sign(...))
将所有非稀疏元素转换为一个,这样您就可以仅使用 colSums
计算列均值:
colSums(dfmtest) / colSums(abs(sign(dfmtest)))
#> [1] 2.285714 2.750000 1.833333 2.625000 2.444444 1.800000 1.875000
#> [8] 2.000000 2.666667 2.333333
我有一个结构类似于此的稀疏矩阵,但要大得多。
library(Matrix)
dfmtest<-new("dgCMatrix"
, i = c(0L, 1L, 2L, 4L, 5L, 6L, 8L, 0L, 1L, 2L, 3L, 4L, 6L, 7L, 8L,
0L, 2L, 3L, 6L, 7L, 8L, 1L, 2L, 4L, 5L, 6L, 7L, 8L, 9L, 0L, 1L,
3L, 4L, 5L, 6L, 7L, 8L, 9L, 0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L,
9L, 0L, 1L, 3L, 4L, 6L, 7L, 8L, 9L, 0L, 2L, 3L, 5L, 6L, 7L, 9L,
0L, 1L, 2L, 3L, 4L, 5L, 6L, 8L, 9L, 0L, 1L, 2L, 3L, 4L, 5L, 6L,
7L, 9L)
, p = c(0L, 7L, 15L, 21L, 29L, 38L, 48L, 56L, 63L, 72L, 81L)
, Dim = c(10L, 10L)
, Dimnames = list(NULL, NULL)
, x = c(4, 3, 1, 2, 3, 1, 2, 1, 3, 3, 2, 3, 3, 3, 4, 2, 1, 2, 3, 2,
1, 4, 1, 2, 2, 3, 2, 3, 4, 1, 4, 1, 3, 4, 3, 2, 2, 2, 4, 1, 2,
2, 1, 2, 3, 1, 1, 1, 4, 1, 1, 2, 1, 1, 1, 4, 3, 3, 2, 1, 2, 2,
1, 1, 3, 3, 4, 1, 2, 4, 2, 4, 1, 2, 2, 3, 4, 2, 1, 2, 4)
, factors = list()
)
我希望能够找到每列(最后是行)的平均值,不包括 0 值。如果我尝试手动执行此操作,由于我的稀疏矩阵的大小,我 运行 会遇到内存问题。
nzmean <- function(x) {
mean(x[x!=0])
}
dfmmeans <- apply(dfmtest, 2, nzmean)
# 1 2 3 4 5 6 7 8
#2.285714 2.750000 1.833333 2.625000 2.444444 1.800000 1.875000 2.000000
# 9 10
#2.666667 2.333333
当我在我的实际矩阵上 运行 以上时,我得到以下错误:
Error in asMethod(object) :
Cholmod error 'problem too large' at file ../Core/cholmod_dense.c, line 105
我也研究过使用 colMeans
函数,但它看起来好像在计算中包含所有 0 值。
dfmmeans <- colMeans(dfmtest)
#[1] 1.6 2.2 1.1 2.1 2.2 1.8 1.5 1.4 2.4 2.1
有没有在大型稀疏矩阵上执行此操作的好方法?
确实colMeans
不支持删除零:
getMethod("colMeans", "dgCMatrix")
#Method Definition:
#
#function (x, na.rm = FALSE, dims = 1, ...)
#{
# .local <- function (x, na.rm = FALSE, dims = 1, sparseResult = FALSE)
# .Call(dgCMatrix_colSums, x, na.rm, sparseResult, FALSE, TRUE)
# .local(x, na.rm, dims, ...)
#}
#<environment: namespace:Matrix>
所以我们需要制定自己的功能。
colMeans_drop0 <- function (dgCMat) {
nnz_per_col <- diff(dgCMat@p)
ColInd <- rep.int(1:ncol(dgCMat), nnz_per_col)
sapply(split(dgCMat@x, ColInd), mean)
}
colMeans_drop0(dfmtest)
# 1 2 3 4 5 6 7 8
#2.285714 2.750000 1.833333 2.625000 2.444444 1.800000 1.875000 2.000000
# 9 10
#2.666667 2.333333
注意:全为零的列将被忽略。同样:
rowMeans_drop0 <- function (dgCMat) {
RowInd <- dgCMat@i + 1
sapply(split(dgCMat@x, RowInd), mean)
}
所有零的行都将被忽略。
备注
summary
+ aggregate
方法是此答案中想法的不同实现方式。
getMethod("summary", "sparseMatrix")
#Method Definition:
#
#function (object, ...)
#{
# d <- dim(object)
# T <- as(object, "TsparseMatrix")
# r <- if (is(object, "nsparseMatrix"))
# data.frame(i = T@i + 1L, j = T@j + 1L)
# else data.frame(i = T@i + 1L, j = T@j + 1L, x = T@x)
# attr(r, "header") <- sprintf("%d x %d sparse Matrix of class \"%s\", with %d entries",
# d[1], d[2], class(object), length(T@i))
# class(r) <- c("sparseSummary", class(r))
# r
#}
#<environment: namespace:Matrix>
summary
首先将任何稀疏矩阵 class 强制转换为 "dgTMatrix"
class,即 三元组格式 ,然后aggregate
内部依赖于 split
+ lapply
。
如果您想保留全零列的结果(当然是 0),使用 colSums
的想法可能是可取的。
的讨论
我们的功能也可以基于 colSums
/ rowSums
实现。
colMeans_drop0 <- function (dgCMat) {
nnz_per_col <- diff(dgCMat@p)
nnz_per_col[nnz_per_col == 0] <- 1 ## just avoid doing 0 / 0
setNames(colSums(dgCMat) / nnz_per_col, 1:ncol(dgCMat))
}
rowMeans_drop0 <- function (dgCMat) {
RowInd <- dgCMat@i + 1
nnz_per_row <- tabulate(RowInd)
nnz_per_row[nnz_per_row == 0] <- 1 ## just avoid doing 0 / 0
setNames(rowSums(dgCMat) / nnz_per_row, 1:nrow(dgCMat))
}
由于 colSums
/ rowSums
删除了 dimnames,我们将它们添加到 setNames
中。这两个函数保留全零列/行的结果。我们还使用 tabulate
函数来有效地计算行中非零条目的数量。
我们可以直接使用tapply
tapply(dfmtest@x,col(dfmtest)[(!dfmtest==0)@x],mean)
1 2 3 4 5 6 7 8 9 10
2.285714 2.750000 1.833333 2.625000 2.444444 1.800000 1.875000 2.000000 2.666667 2.333333
或者你可以
Matrix 有一个很好的 summary
方法,即 returns 矩阵中非零元素的 i、j、x 数据框,可以使用 aggregate
轻松总结(或者 dplyr 或 data.table,如果你愿意的话):
library(Matrix)
str(summary(dfmtest))
#> Classes 'sparseSummary' and 'data.frame': 81 obs. of 3 variables:
#> $ i: int 1 2 3 5 6 7 9 1 2 3 ...
#> $ j: int 1 1 1 1 1 1 1 2 2 2 ...
#> $ x: num 4 3 1 2 3 1 2 1 3 3 ...
#> - attr(*, "header")= chr "10 x 10 sparse Matrix of class \"dgCMatrix\", with 81 entries"
aggregate(x ~ j, summary(dfmtest), mean)
#> j x
#> 1 1 2.285714
#> 2 2 2.750000
#> 3 3 1.833333
#> 4 4 2.625000
#> 5 5 2.444444
#> 6 6 1.800000
#> 7 7 1.875000
#> 8 8 2.000000
#> 9 9 2.666667
#> 10 10 2.333333
如果您想要纯矩阵操作版本,可以使用 abs(sign(...))
将所有非稀疏元素转换为一个,这样您就可以仅使用 colSums
计算列均值:
colSums(dfmtest) / colSums(abs(sign(dfmtest)))
#> [1] 2.285714 2.750000 1.833333 2.625000 2.444444 1.800000 1.875000
#> [8] 2.000000 2.666667 2.333333