Подтвердить что ты не робот

Как вставить столбец в матрицу, правильный путь 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
4b9b3361

Ответ 1

Ваш двойной метод Transpose кажется прекрасным. Для очень больших матриц это будет в 2-3 раза быстрее:

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

Если вы хотите подражать вашему методу Matlab, ближайший, вероятно, следующий:

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

Имейте в виду, что для вставки требуется создать полную копию матрицы. Итак, если вы планируете построить матрицу таким образом, более эффективно предварительно распределить матрицу (если вы знаете ее размер) и вместо этого внести изменения на месте Part.

Ответ 2

Вы можете использовать Join с спецификацией уровня 2 вместе с разделом в подмножествах размера 1:

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

Ответ 3

Я думаю, что я сделал бы это так же, но вот некоторые другие способы сделать это:

-With MapIndexed

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

-With Sequence:

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

Интересно, что это, казалось бы, метод, который работает "на месте", т.е. на самом деле не требуется матричная копия, как указано в ответе Леонида, и если вы напечатаете полученную матрицу, она, по-видимому, работает как прелесть.

Однако существует большой catch. См. Проблемы с Sequence в обсуждении в mathgroup "недопустимое поведение в заданной последовательности.

Ответ 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}}

Я не знаю, как он сравнивается с точки зрения эффективности.

Ответ 5

Я изначально разместил это как комментарий (теперь удален)

Основываясь на методе user656058 в этом вопросе (функция Mathematica Append To Проблема) и ответ 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

Edit

Возможно, проще, хотя бы для меньших матриц

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

или, чтобы вставить столбец нулей

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

Или, немного более широко:

[email protected][a[[#]], {0, 0}, 2] & /@ Range[3] // MatrixForm

Может также легко адаптироваться для работы с Append и Prepend, конечно.