为什么在相同的正则矩阵和稀疏矩阵上应用对数函数时结果不同?

Why are results different when a logarithmic function is applied on same regular matrix and Sparse Matrix?

当我尝试对相同的正则矩阵和稀疏矩阵应用 log 函数时,获得的结果不同。在应用这些功能时有什么我应该记住的吗?下面是一个可重现的例子。

TestMatrix = matrix(c(3,1,0,0,0,4,0,1,0,0,2,1,1,2,0,6,1,0,1,0,1,0,0,0,0),5,byrow = TRUE)
TestSparseMatrix = Matrix(TestMatrix,sparse = TRUE)
# Logarithmic function when applied to regular matrix
 -log(TestMatrix / rowSums(TestMatrix), 2)


#Output
#          [,1]     [,2]     [,3]     [,4] [,5]
#[1,] 0.4150375 2.000000      Inf      Inf  Inf
#[2,] 0.3219281      Inf 2.321928      Inf  Inf
#[3,] 1.5849625 2.584963 2.584963 1.584963  Inf
#[4,] 0.4150375 3.000000      Inf 3.000000  Inf
#[5,] 0.0000000      Inf      Inf      Inf  Inf


# Logarithmic function when applied to Sparse matrix
-log(TestSparseMatrix / rowSums(TestSparseMatrix), 2)


# Output
#          [,1]     [,2]     [,3]     [,4] [,5]
#[1,] 0.2876821 1.386294      Inf      Inf  Inf
#[2,] 0.2231436      Inf 1.609438      Inf  Inf
#[3,] 1.0986123 1.791759 1.791759 1.098612  Inf
#[4,] 0.2876821 2.079442      Inf 2.079442  Inf
#[5,] 0.0000000      Inf      Inf      Inf  Inf

log() 忽略稀疏矩阵("S4" 对象)的 base。使用 log2 消除了问题:

-log2(TestSparseMatrix / rowSums(TestSparseMatrix))

阅读 ?log 的 "S4 methods" 部分。我相信这不是众所周知的。

Note that this means that the S4 generic for ‘log’ has a signature
with only one argument, ‘x’, but that ‘base’ can be passed to
methods (but will not be used for method selection).  On the other
hand, if you only set a method for the ‘Math’ group generic then
‘base’ argument of ‘log’ will be ignored for your class.

如果您想知道,可以继续阅读:

?groupGeneric
?S4groupGeneric

或等效的(因为您将被重定向到上述手册页):

?base::Math
?methods::Math

这确实与 "Math" 组的定义方式有关。特引自?S4groupGeneric:

Note that two members of the ‘Math’ group, ‘log’ and ‘trunc’, have
... as an extra formal argument.  Since methods for ‘Math’ will
have only one formal argument, you must set a specific method for
these functions in order to call them with the extra argument(s).

那么如果你想用任意有效的 base 取对数,比如 base = 3 怎么办?使用公式:

log(x, base = 3) = log(x) / log(3)

例如,使用您的 TestSparseMatrix,您还可以:

-log(TestSparseMatrix / rowSums(TestSparseMatrix)) / log(2)