Эффективный способ выбрать / удалить список строк / столбцов в матрице в Mathematica - PullRequest
4 голосов
/ 14 марта 2011

Этот вопрос является продолжением вопроса, который я задал здесь: Простой способ удаления столбца матрицы в Mathematica , на который @belisarius и @Daniel предоставили очень полезные ответы.

То, что я обычно пытаюсь сделать, - это извлечь из матрицы A определенные строки и столбцы ИЛИ то, что остается после того, что те, которые указаны, удалены.Таким образом, это может быть формально записано как, найдите TakeOperator и Drop Operator так, чтобы:

TakeOperator [A, {i1, .., ip}, {j1, ..., jq}] = (A [[ik]] [[jl]]) (1 <= k <= p, 1 <= l <= q) = <code>Table[A[[ik]][[jl]],{k,p},{l,q}]

Отметим Ic = {i'1, ..., i'р'} = Complement [{1, ..., Length[A]}, {i1, ..., ф}]; Jc = {J'1, ..., j'q '} = Complement [{1, ..., Length[A]}, {j1, ..., jq}];

DropOperator [A, {i1, .., ip}, {j1, ..., jq}] = (A [[ik]] [[jl]]) (1 <= k '<= p', 1 <= l '<= q') = <code>Table[A[[ik']][[jl']],{k',p'},{l','q}]

В то время как Table, как описано выше, делает свое дело, использовать Table таким образом крайне неэффективно.

Просто, чтобы дать идею, я взял пример @ belisarius:

In: First@Timing[a = RandomInteger[1000, {5000, 5000}];]

Out:0.218

In:Clear[b,c]

In:First@Timing[
  b = Table[
    If[i < 100, If[j < 100, a[[i]][[j]], a[[i]][[j + 1]]], 
     If[j < 100, a[[i + 1]][[j]], a[[i + 1]][[j + 1]]]], {i, 
     4999}, {j, 4999}]]

Out:140.807

In:First@Timing[c = Drop[a, {100}, {100}]]

Out:0.093

In:c===b

Out:True

Примечание. Что касается использования Drop в предыдущем посте, я подумал и об его использовании., но когда я проверил документацию, не было никакого предложения сделать это так, как предлагали @belisarius и @daniel.Если бы документация могла обновляться в этом направлении в будущих выпусках, это было бы полезно.

Ответы [ 2 ]

8 голосов
/ 14 марта 2011

Part напрямую поддерживает списки индексов при нарезке массивов.Следующие определения используют это:

takeOperator[a_?MatrixQ, rows_List, cols_List] :=
  a[[rows, cols]]

dropOperator[a_?MatrixQ, rows_List, cols_List] :=
 a[[##]]& @@ complementaryIndices[a, rows, cols]

complementaryIndices[a_?MatrixQ, rows_List, cols_List] :=
  Complement @@@ Transpose @ {Range /@ Dimensions @ a, {rows, cols}}

Пример использования:

a = RandomInteger[1000, {5000, 5000}];
First @ Timing @ takeOperator[a, Range[1, 5000, 2], Range[1, 5000, 2]]
(* 0.016 *)

First @ Timing @ dropOperator[a, Range[1, 5000, 2], Range[1, 5000, 2]]
(* 0.015 *)
3 голосов
/ 14 марта 2011

Вы также можете использовать явные диапазоны довольно эффективным способом. Они могут обеспечить больше гибкости. Вот ваш пример.

a = RandomInteger[1000, {5000, 5000}];

Timing[b = Drop[a, {101}, {101}];]

Out [66] = {0.041993, Null}

Timing[
  c = a[[Join[Range[100], Range[102, 5000]], 
   Join[Range[100], Range[102, 5000]]]];]

Out [67] = {0.061991, Null}

c == b

Out [62] = True

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

Даниэль Лихтблау Wolfram Research

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...