Comment insérer une colonne dans une matrice, la bonne façon Mathematica

je pense que Mathematica est biaisé vers les rangées et non les colonnes.

avec une matrice, il semble facile d'insérer une ligne, il suffit d'utiliser 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

mais pour insérer une colonne, après un certain combat, j'ai trouvé 2 façons, je montre ci-dessous, et je voudrais demander aux experts ici s'ils voient un chemin plus court et plus direct (Mathematica a tellement de commandes, et j'aurais pu négliger un qui fait ce genre de chose de manière beaucoup plus directe), comme je pense les méthodes que j'ai maintenant sont encore trop complexe pour un fonctionnement de base.

première méthode

double transposition:

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

deuxième méthode

utilisez SparseArray, mais il faut faire attention à l'emplacement de l'index. Un peu gênant pour le faire:

(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

La question est: Est-il plus fonctionnelle, qui est peu plus courte que la précédente? Je pourrais bien sûr utiliser l'un des ci-dessus, et envelopper le tout avec une fonction, disons insertColumn[...] pour le rendre facile à utiliser. Mais je voulais voir s'il y avait un moyen plus facile de faire ça que ce que j'ai.

pour référence, c'est comme ça que je fais dans 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
21
demandé sur Matt 2011-09-24 10:17:49

5 réponses

votre double Transpose méthode semble très bien. Pour les très grandes matrices, ce sera 2-3 fois plus rapide:

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

si vous voulez imiter votre voie Matlab, la plus proche est probablement celle-ci:

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

gardez à l'esprit que les insertions nécessitent de faire une copie complète de la matrice. Donc, si vous prévoyez de construire une matrice de cette façon, il est plus efficace de préallouer la matrice (si vous connaissez sa taille) et de faire des modifications en place à travers Part à la place.

18
répondu Leonid Shifrin 2011-09-24 07:30:35

vous pouvez utiliser joindre avec une spécification de niveau de 2 avec une Partition dans les sous-ensembles de taille 1:

a = {{1, 2, 3}, {4, 0, 8}, {7 , 8, 0}}
column = {97, 98, 99}
newa = Join[a,Partition[column,1],2]
8
répondu Bob Jones 2015-07-17 14:29:04

je pense que je le ferais de la même façon, Mais voici d'autres façons de le faire:

- avec MapIndexed

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

- avec Sequence :

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

fait intéressant, il semblerait que ce soit une méthode qui fonctionne "en place", c'est-à-dire qu'il ne serait pas vraiment nécessaire d'une copie de matrice comme indiqué dans la réponse de Leonid et si vous imprimez la matrice résultant, il fonctionne apparemment comme un charme.

cependant, il y a une grosse prise . Voir les problèmes avec Sequence dans la discussion de mathgroup " partie assigned sequence behavior puzzling ".

7
répondu Sjoerd C. de Vries 2011-09-24 08:42:24

d'habitude, je fais comme ça:

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}}

je ne sais pas comment comparer en termes d'efficacité.

4
répondu Phil 2011-09-24 18:32:58

j'ai initialement posté ceci comme un commentaire (maintenant supprimé)

basé sur une méthode donnée par user656058 dans cette "question 1519150920" ( Mathematica 'ajoute à' Problème de fonction ) et la réponse de Mr Wizard , la méthode alternative suivante d'ajouter une colonne à une matrice, en utilisant Table and Insert , may be gleaned:

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

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

donnant

enter image description here

de même, pour ajouter une colonne de zéros (say):

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

comme indiqué dans les commentaires ci-dessus, Janus a attiré l'attention sur le "truc" d'ajouter une colonne de zéros par la méthode ArrayFlatten (voir ici )

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

Modifier

peut-être plus simple, au moins pour les plus petites matrices

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

ou, pour insérer une colonne de zéros

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

Ou, un peu plus général:

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

peut aussi facilement être adapté pour fonctionner avec Append et Prepend , bien sûr.

4
répondu tomd 2017-05-23 11:54:26