如何将列插入矩阵,正确的Mathematica方式

Nas*_*ser 22 wolfram-mathematica

我认为Mathematica偏向于行而不是列.

给定一个矩阵,插入一行似乎很容易,只需使用 Insert[]

(a = {{1, 2, 3}, {4, 0, 8}, {7 , 8, 0}}) // MatrixForm

1   2    3
4   0    8
7   8    0

 row = {97, 98, 99};
(newa = Insert[a, row, 2]) // MatrixForm

1   2   3
97  98  99
4   0   8
7   8   0
Run Code Online (Sandbox Code Playgroud)

但是为了插入一个专栏,经过一番努力之后,我找到了两种方法,我在下面展示,如果他们看到更短更直接的方式,我想问问专家(Mathematica有这么多命令,我可能忽略了一个这种事情以非常直接的方式完成),因为我认为我现在拥有的方法对于这样的基本操作来说仍然过于复杂.

第一种方法

必须做双转置:

a = {{1, 2, 3}, {4, 0, 8}, {7 , 8, 0}}
column = {97, 98, 99}
newa = Transpose[Insert[Transpose[a], column, 2]]

1   97  2   3
4   98  0   8
7   99  8   0
Run Code Online (Sandbox Code Playgroud)

第二种方法

使用SparseArray,但需要注意索引位置.有点尴尬这样做:

(SparseArray[{{i_, j_} :> column[[i]] /; j == 2, {i_, j_} :> a[[i, j]] /; j == 1, 
              {i_, j_} :> a[[i, j - 1]] /; j > 1}, {3, 4}]) // Normal

1   97  2   3
4   98  0   8
7   99  8   0
Run Code Online (Sandbox Code Playgroud)

问题是:是否有更多功能性方式,比上述方式短一些?我当然可以使用上面的一个,用一个函数包装整个东西,比如insertColumn[...]让它易于使用.但是想看看有没有比我更简单的方法来做到这一点.

作为参考,这是我在Matlab中的方法:

EDU>> A=[1 2 3;4 0 8;7 8 0]
A =
     1     2     3
     4     0     8
     7     8     0

EDU>> column=[97 98 99]';

EDU>> B=[A(:,1) column A(:,2:end)]

B =
     1    97     2     3
     4    98     0     8
     7    99     8     0
Run Code Online (Sandbox Code Playgroud)

Leo*_*rin 18

你的双重Transpose方法似乎很好.对于非常大的矩阵,这将快2-3倍:

MapThread[Insert, {a, column, Table[2, {Length[column]}]}]
Run Code Online (Sandbox Code Playgroud)

如果你想模仿你的Matlab方式,最接近的可能就是:

ArrayFlatten[{{a[[All, ;; 1]], Transpose[{column}], a[[All, 2 ;;]]}}]
Run Code Online (Sandbox Code Playgroud)

请记住,插入需要制作矩阵的完整副本.因此,如果您计划以这种方式构建矩阵,则预分配矩阵(如果您知道其大小)并通过Part相反进行就地修改会更有效.


小智 8

您可以在级别为1的子集中使用级别规范为2的Join和Partition:

a = {{1, 2, 3}, {4, 0, 8}, {7 , 8, 0}}
column = {97, 98, 99}
newa = Join[a,Partition[column,1],2]
Run Code Online (Sandbox Code Playgroud)


Sjo*_*ies 7

我想我会以同样的方式做到这一点,但这里还有其他一些方法:

- 随着 MapIndexed

newa = MapIndexed[Insert[#1, column[[#2[[1]]]], 2] &, a]
Run Code Online (Sandbox Code Playgroud)

- 用Sequence:

newa = a;
newa[[All, 1]] = Transpose[{newa[[All, 1]], column}];
newa = Replace[a, List -> Sequence, {3}, Heads -> True]
Run Code Online (Sandbox Code Playgroud)

有趣的是,这似乎是一种"就地"工作的方法,即它不会真正需要像Leonid的答案中所述的矩阵复制,如果你打印出结果矩阵,它显然可以作为一种魅力.

然而,有一个很大的问题.请参阅Sequence数学组讨论中的问题" 部分分配的序列行为令人费解 ".

  • +1.你提到的问题是我没有使用基于序列的方法的一个原因.以下是两个更相关的链接,一个是最近的链接:http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/b7303eafccee6d5a和http://groups.google.com/组/ comp.soft-sys.math.mathematica/browse_thread /线程/ 8d04685fd7283130.我通常对基于"序列"的作业持否定态度,原因是我在帖子中提到的那些主题.不使用`Sequence`的另一个原因是这将导致打包矩阵的解包. (3认同)
  • 顺便说一句,使用`Sequence`的方法*仍会*导致复制,它只是更好地隐藏.当你执行`Insert'时,复制在定义时完成.使用基于"序列"的方法,在"序列" - 评估的拼接步骤期间,在运行时完成复制.在这方面,我考虑一个列表的例子 - 在MathLink的文档中使用`Sequence`构建:http://reference.wolfram.com/mathematica/tutorial/HandlingListsArraysAndOtherExpressions.html特别具有误导性.它们强调性能,但忽略了这种方法具有二次复杂性的事实(如`Append`). (3认同)