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

时间:2011-09-24 06:17:50

标签: 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

但是为了插入一个专栏,经过一番努力之后,我找到了两种方法,我在下面展示,并想问这里的专家是否看到更短更直接的方式(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

第二种方法

使用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

问题是:是否有更多功能性方式,比上述方式短一些?我当然可以使用上面的一个,并用函数包装整个事件,比如说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

5 个答案:

答案 0 :(得分:18)

您的双Transpose方法似乎没问题。对于非常大的矩阵,这将快2-3倍:

MapThread[Insert, {a, column, Table[2, {Length[column]}]}]

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

ArrayFlatten[{{a[[All, ;; 1]], Transpose[{column}], a[[All, 2 ;;]]}}]

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

答案 1 :(得分:8)

您可以在级别为1的子集中使用级别规范为2的连接以及分区:

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

答案 2 :(得分:7)

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

- 与MapIndexed

newa = MapIndexed[Insert[#1, column[[#2[[1]]]], 2] &, a]

- 与Sequence

newa = a;
newa[[All, 1]] = Transpose[{newa[[All, 1]], column}];
newa = Replace[a, List -> Sequence, {3}, Heads -> True]

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

但是,有一个大问题。在数学小组讨论“part assigned sequence behavior puzzling”中查看Sequence的问题。

答案 3 :(得分:4)

我通常只是这样做:

In: m0 = ConstantArray[0, {3, 4}]; 
    m0[[All, {1, 3, 4}]] = {{1, 2, 3}, {4, 0, 8}, {7, 8, 0}}; 
    m0[[All, 2]] = {97, 98, 99}; m0 

Out: 
    {{1, 97, 2, 3}, {4, 98, 0, 8}, {7, 99, 8, 0}}

我不知道它在效率方面的比较。

答案 4 :(得分:4)

我最初将此作为评论发布(现已删除)

基于user656058问题( Mathematica'附加到'函数问题)和this replyMr Wizard给出的方法,可以收集使用TableInsert向列表添加列的以下替代方法:

(a = {{1, 2, 3}, {4, 0, 8}, {7, 8, 0}});
column = {97, 98, 99};

Table[Insert[a[[i]], column[[i]], 2], {i, 3}] // MatrixForm

enter image description here

同样,要添加一列零(例如):

Table[Insert[#[[i]], 0, 2], {i, Dimensions[#][[1]]}] & @ a 

正如上面的评论中所述,Janus引起了人们对ArrayFlatten方法添加一列零的“技巧”的关注(参见here

ArrayFlatten[{{Take[#, All, 1], 0, Take[#, All, -2]}}] & @ 
  a // MatrixForm

修改

也许更简单,至少对于较小的矩阵

(Insert[a[[#]], column[[#]], 2] & /@ Range[3]) // MatrixForm

或者,插入一列零

Insert[a[[#]], 0, 2] & /@ Range[3]

或者,更一般地说:

Flatten@Insert[a[[#]], {0, 0}, 2] & /@ Range[3] // MatrixForm

当然也可以很容易地适应AppendPrepend