8
$\begingroup$

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).

$\endgroup$
  • 1
    $\begingroup$ Delete[Transpose@A, {{4}, {7}}] // Transpose $\endgroup$ – OkkesDulgerci Sep 6 '18 at 12:51
  • 1
    $\begingroup$ mA[[All, Complement[Range[11], {4, 7}]]] $\endgroup$ – Alan Sep 6 '18 at 13:18
4
$\begingroup$

I am confused by the complexity of many of these responses. The single command

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[A, None, {9}], None, {1,3,2}]

or equivalently,

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:

Fold[Drop[#1, None, {#2}]&, A, Reverse[c]]

$\endgroup$
  • 1
    $\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
8
$\begingroup$

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

Mathematica graphics

ReplacePart[a, {{_, 4}, {_, 7}} :> Sequence[]];
MatrixForm[%]

Mathematica graphics

$\endgroup$
  • $\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
  • 1
    $\begingroup$ Again, my obligatory warning: This method unpacks arrays. $\endgroup$ – Henrik Schumacher Sep 6 '18 at 19:48
8
$\begingroup$

The fasted way to do this is to use Part and construct the indices you need to take using 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
$\endgroup$
5
$\begingroup$
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 
$\endgroup$
  • $\begingroup$ How can you delete two or more columns? $\endgroup$ – OkkesDulgerci 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
3
$\begingroup$

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.

 SeedRandom@2;
    A = RandomInteger[25, {9, 11}];
    MatrixForm@A

$A=\left( \begin{array}{ccccccccccc} 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 \\ \end{array} \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( \begin{array}{cccccccc} 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 \\ \end{array} \right)$

$\endgroup$
2
$\begingroup$
MapThread[Delete, {A, ConstantArray[{{4}, {7}}, Length[A]]}]
$\endgroup$
2
$\begingroup$

You can also use a combination of Fold and 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

$\small\left( \begin{array}{ccccccc} 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} \\ \end{array} \right)$

dropCols1[m, {4, 7, 1}] // MatrixForm // TeXForm

$\small\left( \begin{array}{cccccc} 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} \\ \end{array} \right)$

Alternatively, (1) assign ##&[] (or Nothing in versions 10+) to the desired columns (dropCols2) or (2) use a combination of MapAt and ##&[]& (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

$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.