将数字列表扩展为矩阵(包含 n 个值的列表乘以 n x n 矩阵)

Expanding a list of numbers into a matrix (list with n values to multiply to a n x n matrix)

我有一组数字,我想将其展开成一个矩阵。 列表中有 4 个值,我想将其扩展为 4x4 矩阵。 这是一些示例数据

freq <- c(627,449,813,111)  

我想把它展开成一个矩阵,这样就变成了这样。 抱歉,我刚刚复制并粘贴了数据,因此它不是 R 输出,但希望它有助于理解这个想法。

    1   2   3   4   Total
1   197 141 255 35  627
2   141 101 183 25  449
3   255 183 330 45  813
4   35  25  45  6   111
    627 449 813 111 2000

单元格是(行总计)x(列总计)/(table 总计)的乘积。 1,1 中的值 = (627 x 627)/2000 = 197。2,1 中的值 = (627 x 449)/2000 = 141,依此类推。

是否有创建该矩阵的函数?我会尝试通过循环来完成,但希望有一个函数或矩阵计算技巧可以更有效地做到这一点?抱歉,如果我没有很好地表达上述内容,我们将不胜感激。谢谢

freq <- c(627,449,813,111) 
round(outer(freq, freq)/sum(freq))
#>      [,1] [,2] [,3] [,4]
#> [1,]  197  141  255   35
#> [2,]  141  101  183   25
#> [3,]  255  183  330   45
#> [4,]   35   25   45    6

这在这里并不重要,但最好避免像 outer(x, x) / sum(x) 这样的结构,而使用像 tcrossprod(x / sqrt(sum(x))):

这样的结构
round(tcrossprod(freq / sqrt(sum(freq))))
##      [,1] [,2] [,3] [,4]
## [1,]  197  141  255   35
## [2,]  141  101  183   25
## [3,]  255  183  330   45
## [4,]   35   25   45    6

outer 方法存在一些问题:

  • outer(x, x) 在内部计算 tcrossprod(as.vector(x), as.vector(x))。如果 x 已经是向量,那么 as.vector 调用和 outer 内部发生的所有其他事情都是完全多余的。 as.vector 调用实际上比冗余更糟糕:如果 x 有任何属性,那么 as.vector(x) 需要 x.
  • 的深层副本
  • 天真地做A <- outer(x, x); A / sum(x)需要R为两个n-by-n矩阵分配内存。对于足够大的 n,即使不是不可能,也是非常浪费的。如果直接计算 outer(x, x) / sum(x),R 足够聪明,可以避免第二次分配。然而,这样的优化是低级的,有很多陷阱,甚至没有记录在 ?Arithmetic 中,因此依赖它们可能是不安全的。
  • 如果 x 的元素非常(非常)小或大,
  • outer(x, x) 会导致下溢或溢出。

tcrossprod(x / sqrt(sum(x))) 通过在计算外积 之前缩放 x 并删除 outer 的所有冗余来避免所有这些问题.