web-dev-qa-db-ja.com

列を行列に挿入する方法、正しい数学の方法

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

しかし、列を挿入するために、いくつかの苦労の末、私は2つの方法を見つけました、以下に示します、そしてここの専門家にもっと短くてより直接的な方法を見ているかどうか尋ねたいと思います(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

2番目の方法

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
22
Nasser

Double Transposeメソッドは問題ないようです。非常に大きな行列の場合、これは2〜3倍高速になります。

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

Matlabの方法を模倣したい場合、最も近いのはおそらくこれです:

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

挿入には、マトリックスのコピー全体を作成する必要があることに注意してください。したがって、この方法でマトリックスを作成する場合は、マトリックスを事前に割り当て(サイズがわかっている場合)、代わりにPartを使用してインプレース変更を行う方が効率的です。

18
Leonid Shifrin

サイズ1のサブセットのパーティションとともに、レベル指定が2の結合を使用できます。

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

私はそれを同じ方法で行うと思いますが、これを行う他のいくつかの方法があります:

-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の回答に記載されているように、実際にはマトリックスコピーを必要とせず、結果のマトリックスを印刷すると、明らかに魅力として機能します。

ただし、大きなキャッチがあります。 mathgroupのディスカッション " 部分的に割り当てられたシーケンス動作が不可解 "のSequenceの問題を参照してください。

7

私は通常このようにします:

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
Phil

私はもともとコメントとしてこれを投稿しました(現在は削除されています)

user656058 in this question(Mathematica'AppendTo)で指定されたメソッドに基づく'関数の問題)および reply of Mr Wizard 、次の追加方法TableおよびInsertを使用して、行列への列を収集できます。

(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メソッドによってゼロの列を追加する「トリック」に注目を集めています( を参照)。 /ここに

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

もちろん、AppendおよびPrependで動作するように簡単に適合させることもできます。

4
tomd