Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Summary:Ways to get Odd Columns&Rows of Matrix

127 views
Skip to first unread message

Xah Y Lee

unread,
Apr 8, 1995, 3:00:00 AM4/8/95
to

This is a summary of Ways to get only odd rows and columns of a matrix.

Problem: Suppose we have a mxn matrix. We want to cross out the even rows
and columns, and get the remaining matrix. How to do that?

This is built-in in mma. The simplest way to do it is
Part[myMatrix,{1,3,5...},{1,3,5...}]. See section 3.7.2, p.651 of the mma
book.
Below is a collection of various ways to write this program. Some of them
are general that can work on matrices with more than 2 dimensions, and
user can choose odd only, even only, or generalized such as every third
member in the tensor. Most others are included not as a practical solution but
as programming examples.

These pieces of codes are contributed by various members of mathgroup.
I've taken the liberty to modify some of them to make this a coherent
summary.

------------
Clear[myList]
myList = Array[a,{10,18}];
------------
(*Using Part*)
(*From: Robert Villegas <vill...@wri.com>*)
(*From: Count Dracula <lk...@kelvin.seas.virginia.edu>*)
(*
In my opinion this is the best solution.
Use Map[Select[Range[#], OddQ] &, Dimensions[myMatrix]] to generate a
list {{1,3,5,..}, {1,3,5,7...}}, then feed it to Part to extract, like
this
Part[myMatrix, {1,3,5}, {1,3,5,7}].*)
*)

MatrixSieve1a[myMatrix_] :=
Part[myMatrix,
Sequence@@ Map[ Range[1, #, 2]&, Dimensions[myMatrix]]
]

MatrixSieve1b[myMatrix_, sel_:OddQ] :=
Part[myMatrix,
Sequence@@ Map[(Select[Range[#], sel] &) , Dimensions[myMatrix]]
]

------------
(*Using Table.*)
(*From: Lou Talman <m...@talmanl.mscd.edu>*)
(*easiest to understand.*)

MatrixSieve2[myMatrix_] :=
Module[{i,j},
Table[ myMatrix[[i, j]],
{i, 1, Length[myMatrix], 2},
{j, 1, Length[First@myMatrix], 2}
]
]
------------
(*using Partition. *)
(*From: Xah Lee <7463...@compuserve.com>*)
(*
This one is hard to understand. It's not easy to generalize as well. It
will not work if the matrix contain odd number of row or column, but it's
got the potential to become the most elegant solution. It's the fastest
among all.
*)
MatrixSieve3[myMatrix_] := Map[ First, Partition[myMatrix,{2,2}],{2,3}]

------------
(*Recursively elimate the second term.*)
(*From: Tyler Perkins <per...@colorado.edu>*)
(*
Define OddOnly[], that will get rid of the second element in a list.
This is repeated recursively in a nested way so that at the end only the
odd terms of the list is left.
Map OddOnly to every level of myList.
*)

OddOnly[{first_, second_, rest___}] := Join[{first}, OddOnly[{rest}]];
OddOnly[singleExpr_] := singleExpr;
MatrixSieve4[myMatrix_] := MapAll[ OddOnly, myMatrix]

------------
(*using Array and Part*)
(*From: "L. Hannibal" <hann...@caesar.physik.uni-oldenburg.de>*)

MatrixSieve5[myMatrix_]:=
Array[
myMatrix[[2 #1 -1,2 #2-1]]&,
{Ceiling[Length[myMatrix]/2], Ceiling[Length@First@myMatrix/2]}
]
------------
(*using Pattern and ReplaceRepeated*)
(*From: Robert Zimmerman <b...@zim.uoregon.edu>*)
(*This is not a general method, but included here as a extra example of
programming techniques. It only works on matrices whos elements have the
form head[x,y]. It works by first flatten myList, then replace elements
with even index with 0, then eliminate the zeros in the list. Lastly,
Partition them into the correct form.
*)
Partition[
(Flatten@myList)//.{a[x_ ,y_?EvenQ ] ->0, a[x_?EvenQ ,y_ ] ->0}//.
{ head___ ,0, tail___ } :> {head, tail}
,3
]
------------
(* using Fold and Drop *)
(*From: bob Hanlon <han...@pafosu2.hq.af.mil>*)
(*works on matrices with even number of terms.
Not a good example of coding.
The use of Fold, Transpose and Drop are too complex.
Slow as well.
*)

Transpose[
Fold[ Drop,
Transpose[
Fold[ Drop, myList,
-Array[List,Length@myList/2]
]
],
-Array[List,Length@First@myList/2]
]
]
------------

Xah Lee
Come! Have compassion toward your fellow human beings! Please send $1 to
650 Alamo CT APT#1, MTN View, CA 94043, US of A to support a future
mathematician to pay off his dentist. You surely agree that teeth are
more important then Mathematica?


Robert Villegas

unread,
Apr 8, 1995, 3:00:00 AM4/8/95
to
> (* using Fold and Drop *)
> (*From: bob Hanlon <han...@pafosu2.hq.af.mil>*)
> (*works on matrices with even number of terms.
> Not a good example of coding.
> The use of Fold, Transpose and Drop are too complex.
> Slow as well.

[bob's original code is here:]

> Fold[ Transpose[ Fold[ Drop, #,

> Table[ {-k}, {k, Length[ u ]/2} ] ] ]&,

> u, {1, 2} ] // MatrixForm
> (* Select odd rows and columns from square matrix *)


> Fold[ Transpose[ Fold[ Drop, #,

> Table[ {-k-1}, {k, Length[ u ]/2} ] ] ]&,

> u, {1, 2} ] // MatrixForm

Actually, I thought Bob's solution was rather clever, even if not as
practical for this application. The cumulative deletion of an
element, moving one further from the end each time, is kind of
neat, and I liked the Transpose for switching focus to the columns
after doing the rows, too. I don't think this would have occurred to
me.

I think some of the weaknesses in terms of generality can be fixed,
preserving the original ideas. I'm not sure it will be as general
as the others, and not as fast, but it seems like a worthwhile programming
and conceptual exercise.


The code works from the end instead of the beginning, and would
have to be changed if you wanted to apply it to an (odd x odd) matrix
instead of (even x even). Perhaps

Fold[Delete, #, 1 + Range[1/2 Length[#]] ]&

This deletes element 2, then 3, then 4, et cetera, to the end or
the (end - 1). I think Delete makes it just a tad easier because
you don't have to wrap the position in a list.

Also, the outer Fold needn't be a Fold, because it uses only one variable,
#1, which is the previous expression in the sequence. You are just
applying the same transformation several times (well, twice for a
2-dim matrix), so Nest will work.


In[47]:= Nest[Transpose @ Fold[Delete, #, 1 + Range[1/2 Length[#]] ]&,
Array[u, {6, 6}], 2]

Out[47]= {{u[1, 1], u[1, 3], u[1, 5]}, {u[3, 1], u[3, 3], u[3, 5]},

> {u[5, 1], u[5, 3], u[5, 5]}}

I think you can generalize it to an n-dimensional tensor, as well.
Use the Transpose idea, giving a rotated list of dimensions as the
second argument to Transpose in this case.

An example for a 3D matrix:


In[41]:= Nest[Transpose[Part[#, Range[1, Length[#], 2]],
RotateRight @ Range[3]]&, Array[a, {5, 6, 7}], 3] //MatrixForm

Out[41]//MatrixForm= a[1, 1, 1] a[1, 3, 1] a[1, 5, 1]
a[1, 1, 3] a[1, 3, 3] a[1, 5, 3]
a[1, 1, 5] a[1, 3, 5] a[1, 5, 5]
a[1, 1, 7] a[1, 3, 7] a[1, 5, 7]

a[3, 1, 1] a[3, 3, 1] a[3, 5, 1]
a[3, 1, 3] a[3, 3, 3] a[3, 5, 3]
a[3, 1, 5] a[3, 3, 5] a[3, 5, 5]
a[3, 1, 7] a[3, 3, 7] a[3, 5, 7]

a[5, 1, 1] a[5, 3, 1] a[5, 5, 1]
a[5, 1, 3] a[5, 3, 3] a[5, 5, 3]
a[5, 1, 5] a[5, 3, 5] a[5, 5, 5]
a[5, 1, 7] a[5, 3, 7] a[5, 5, 7]

I think this general coding will work for higher tensors. The levels of
the tensor get rotated around a full cycle, and end up where they were
originally:

everyother[tensor_List] :=
With[{n = TensorRank[tensor]},
Nest[Transpose[Part[#, Range[1, Length[#], 2]], RotateRight @ Range[n]]&,

tensor, n]
]


A test, using a matrix whose entries are just the indices concatenated
together, for compactness of display (I always use this sort of thing
when I'm having difficulty visualizing what's going on with higher
dimensional matrices):


In[29]:= everyother[ Array[SequenceForm, {3, 4, 5, 6}] ] //MatrixForm

Out[29]//MatrixForm= 1111 1113 1115 1311 1313 1315
1131 1133 1135 1331 1333 1335
1151 1153 1155 1351 1353 1355

3111 3113 3115 3311 3313 3315
3131 3133 3135 3331 3333 3335
3151 3153 3155 3351 3353 3355


Robby Villegas


0 new messages