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