How to delete arbitrary numbers of columns from a matrix in mathematica [duplicate]
How to delete arbitrary numbers of columns from a matrix in mathematica [duplicate]
This question already has an answer here:
Say I have a matrix of random integers, which is given by
A=RandomInteger[25, 9, 11]
How can specific columns of this matrix (say 4th and 7th columns) be deleted?
EDIT
It is really surprising that some people has found this question duplicate. I have asked for two specific columns, but it can be extended to any numbers of columns. Say I have a matrix of (985 x 1123), and I want to delete column no. 18, 37, 54, 85, 305, 564 and 1029 from the original matrix to get a new matrix of size (985 x 1116).
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
Delete[Transpose@A, 4, 7] // Transpose
$begingroup$
mA[[All, Complement[Range[11], 4, 7]]]
$endgroup$
– Alan
Sep 6 '18 at 13:18
mA[[All, Complement[Range[11], 4, 7]]]
7 Answers
7
I am confused by the complexity of many of these responses. The single command
Drop[A, None, 4,7,3]
Drop[A, None, 4,7,3]
is sufficient to remove columns $4$ and $7$, in steps of $3$ (so as not to remove columms $5$ and $6$). If you wanted to remove more than two columns that are not separated by an equal number of columns, then you would need to use Drop
more than once, starting from the rightmost column to be removed; e.g., to remove columns $1$, $3$, and $9$, you could just do
Drop
Drop[Drop[A, None, 9], None, 1,3,2]
Drop[Drop[A, None, 9], None, 1,3,2]
or equivalently,
Drop[Drop[A, None, 3,9,6], None, 1]
Drop[Drop[A, None, 3,9,6], None, 1]
If you had an arbitrary sorted list of column indices to remove, which we might call c
, then Fold
is trivially applied:
c
Fold
Fold[Drop[#1, None, #2]&, A, Reverse[c]]
Fold[Drop[#1, None, #2]&, A, Reverse[c]]
$begingroup$
I considered
Drop
, but because you cannot give give it an arbitrary list of column indices, I decided that Part
is more suited for the job. Especially because repeated calls to Drop
is going to be slow for large matrices.$endgroup$
– Sjoerd Smit
Sep 7 '18 at 8:15
Drop
Part
Drop
I learned this method long time ago from Mr Wizard answer, it works well. But there are many other ways
a = RandomInteger[25, 9, 11];
a // MatrixForm
ReplacePart[a, _, 4, _, 7 :> Sequence];
MatrixForm[%]
$begingroup$
Some variations on this theme. Mr.Wizard's
(## &)
can be substituted for Sequence
. In recent versions of Mathematica, substituting Nothing
works too.$endgroup$
– m_goldberg
Sep 6 '18 at 17:56
(## &)
Sequence
Nothing
$begingroup$
Again, my obligatory warning: This method unpacks arrays.
$endgroup$
– Henrik Schumacher
Sep 6 '18 at 19:48
The fasted way to do this is to use Part
and construct the indices you need to take using Complement
:
Part
Complement
dropColumns[mat_?MatrixQ, columns : __Integer] := With[
columnsToTake = Complement[
Range[Dimensions[mat][[2]]],
columns
]
,
mat[[All, columnsToTake]]
];
a = RandomInteger[25, 9, 11];
a // MatrixForm
dropColumns[a, 2, 5] // MatrixForm
A = RandomInteger[25, 9, 11];
A // MatrixForm
DeleteCol[Matrix_, indexlist_] :=
Block[internalMatrix = Matrix, i, k = 0,
internallist = SortBy[indexlist, Smaller],
For[i = 1, i <= Length[internallist], i++,
internalMatrix =
Delete[Transpose[internalMatrix], internallist[[i]] - k];
internalMatrix = Transpose[internalMatrix];
k++;
];
internalMatrix
];
DeleteCol[A, 4, 7];
% // MatrixForm
DeleteCol[A, 7, 4];
% // MatrixForm
$begingroup$
How can you delete two or more columns?
$endgroup$
– Okkes Dulgerci
Sep 6 '18 at 13:25
$begingroup$
@Okkes Dulgerci now it's possible to delete two or more columns.
$endgroup$
– Diogo
Sep 6 '18 at 17:28
Here is another way to do it. I assume that columns you want delete is ordered. i.e. 4,7
will work but 7,4
won't.
4,7
7,4
SeedRandom@2;
A = RandomInteger[25, 9, 11];
MatrixForm@A
$A=left(
beginarrayccccccccccc
23 & 3 & 18 & 11 & 10 & 17 & 8 & 3 & 8 & 0 & 19 \
9 & 23 & 25 & 24 & 14 & 4 & 3 & 4 & 12 & 12 & 8 \
8 & 18 & 6 & 3 & 1 & 14 & 21 & 4 & 14 & 10 & 20 \
22 & 8 & 10 & 20 & 19 & 1 & 9 & 12 & 0 & 19 & 11 \
25 & 10 & 8 & 7 & 18 & 7 & 9 & 23 & 1 & 6 & 15 \
12 & 1 & 0 & 14 & 19 & 12 & 2 & 5 & 3 & 7 & 5 \
23 & 24 & 1 & 14 & 3 & 2 & 22 & 16 & 21 & 4 & 11 \
4 & 2 & 3 & 20 & 24 & 8 & 10 & 3 & 6 & 12 & 19 \
20 & 24 & 6 & 1 & 13 & 10 & 8 & 21 & 5 & 6 & 21 \
endarray
right)$
deleteColumns[mat_?MatrixQ, col_] :=
With[column = col - Range[0, Length@col - 1],
Fold[Delete[#, #2] &, Transpose@A, column] // Transpose]
deleteColumns[A, 4, 7, 10] // MatrixForm
$A=left(
beginarraycccccccc
23 & 3 & 18 & 10 & 17 & 3 & 8 & 19 \
9 & 23 & 25 & 14 & 4 & 4 & 12 & 8 \
8 & 18 & 6 & 1 & 14 & 4 & 14 & 20 \
22 & 8 & 10 & 19 & 1 & 12 & 0 & 11 \
25 & 10 & 8 & 18 & 7 & 23 & 1 & 15 \
12 & 1 & 0 & 19 & 12 & 5 & 3 & 5 \
23 & 24 & 1 & 3 & 2 & 16 & 21 & 11 \
4 & 2 & 3 & 24 & 8 & 3 & 6 & 19 \
20 & 24 & 6 & 13 & 10 & 21 & 5 & 21 \
endarray
right)$
MapThread[Delete, A, ConstantArray[4, 7, Length[A]]]
You can also use a combination of Fold
and Drop
:
Fold
Drop
ClearAll[dropCols1]
dropCols1 = Fold[Drop[#, None, #2] &, #, List /@ Reverse @ Sort[#2]] &;
Examples:
m = Array[Subscript[a, ##] &, 9, 9];
dropCols1[m, 4, 7] // MatrixForm // TeXForm
$smallleft(
beginarrayccccccc
a_1,1 & a_1,2 & a_1,3 & a_1,5 & a_1,6 & a_1,8 & a_1,9 \
a_2,1 & a_2,2 & a_2,3 & a_2,5 & a_2,6 & a_2,8 & a_2,9 \
a_3,1 & a_3,2 & a_3,3 & a_3,5 & a_3,6 & a_3,8 & a_3,9 \
a_4,1 & a_4,2 & a_4,3 & a_4,5 & a_4,6 & a_4,8 & a_4,9 \
a_5,1 & a_5,2 & a_5,3 & a_5,5 & a_5,6 & a_5,8 & a_5,9 \
a_6,1 & a_6,2 & a_6,3 & a_6,5 & a_6,6 & a_6,8 & a_6,9 \
a_7,1 & a_7,2 & a_7,3 & a_7,5 & a_7,6 & a_7,8 & a_7,9 \
a_8,1 & a_8,2 & a_8,3 & a_8,5 & a_8,6 & a_8,8 & a_8,9 \
a_9,1 & a_9,2 & a_9,3 & a_9,5 & a_9,6 & a_9,8 & a_9,9 \
endarray
right)$
dropCols1[m, 4, 7, 1] // MatrixForm // TeXForm
$smallleft(
beginarraycccccc
a_1,2 & a_1,3 & a_1,5 & a_1,6 & a_1,8 & a_1,9 \
a_2,2 & a_2,3 & a_2,5 & a_2,6 & a_2,8 & a_2,9 \
a_3,2 & a_3,3 & a_3,5 & a_3,6 & a_3,8 & a_3,9 \
a_4,2 & a_4,3 & a_4,5 & a_4,6 & a_4,8 & a_4,9 \
a_5,2 & a_5,3 & a_5,5 & a_5,6 & a_5,8 & a_5,9 \
a_6,2 & a_6,3 & a_6,5 & a_6,6 & a_6,8 & a_6,9 \
a_7,2 & a_7,3 & a_7,5 & a_7,6 & a_7,8 & a_7,9 \
a_8,2 & a_8,3 & a_8,5 & a_8,6 & a_8,8 & a_8,9 \
a_9,2 & a_9,3 & a_9,5 & a_9,6 & a_9,8 & a_9,9 \
endarray
right)$
Alternatively, (1) assign ##&
(or Nothing
in versions 10+) to the desired columns (dropCols2
) or (2) use a combination of MapAt
and ##&&
(dropCols3
):
##&
Nothing
dropCols2
MapAt
##&&
dropCols3
ClearAll[dropCols2, dropCols3]
dropCols2 = Module[a = #, a[[All, #2]] = ## &; a] &;
dropCols3 = MapAt[## & &, #, All, #2] &;
Equal @@ (#[m, 4, 7] & /@ dropCols1, dropCols2, dropCols3)
True
Equal @@ (#[m, 4, 7, 1] & /@ dropCols1, dropCols2, dropCols3)
True
$begingroup$
Delete[Transpose@A, 4, 7] // Transpose
$endgroup$
– Okkes Dulgerci
Sep 6 '18 at 12:51