Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have f.e. the following square matrix:

x = {{2, 5, 5, 11, 11, 23, 37, 41, 43, 47},
    {2, 5, 11, 17, 19, 23, 41, 41, 43, 67},
    {2, 7, 11, 19, 19, 41, 41, 43, 47, 73},
    {3, 11, 17, 19, 23, 41, 43, 53, 67, 79},
    {3, 11, 19, 19, 31, 43, 47, 59, 67, 83},
    {3, 17, 19, 29, 37, 43, 53, 59, 73, 83},
    {5, 17, 29, 31, 37, 47, 53, 71, 73, 83},
    {7, 19, 29, 31, 37, 53, 59, 73, 73, 89},
    {11, 23, 31, 41, 43, 53, 61, 73, 79, 97},
    {29, 29, 37, 41, 53, 67, 71, 79, 79, 97}};

I want to keep the first and last row / column and replace all other numbers with 0. I have written:

n = Length@First@x;

Table[x[[i, j]] = 0, {i, 2, n - 1}, {j, 2, n - 1}];

x // MatrixForm

enter image description here

Before that I tried to find a more functional solution (f.e. with replacement patterns) but gave up after some unsuccesful attempts. Thanks for showing me some alternatives.

share|improve this question

8 Answers 8

up vote 11 down vote accepted

Just another alternative.

x - ArrayPad[ArrayPad[x, -1], 1] // MatrixForm
share|improve this answer
1  
Quite an unusual approach but I like it. –  Mr.Wizard Jul 9 at 19:32
3  
Could also be written: x - Fold[ArrayPad, x, {-1, 1}] –  Mr.Wizard Jul 9 at 19:52
    
@Pickett Without doing any speed comparisons I would like to accept your answer because it is so clever and, like Mr. Wizard remarked, "unusual". –  eldo Jul 10 at 1:38
    
@eldo Thank you! :) –  Pickett Jul 10 at 9:14

You can do:

x[[2 ;; -2, 2 ;; -2]] = 0;
x

or

ReplacePart[x, {i, j} -> 0 /; And @@ MapThread[Less, {{1, 1}, {i, j}, Dimensions@x}]]
share|improve this answer
    
Probably THE answer. Actually I tried Part but wasn't able to find your sequence. –  eldo Jul 9 at 19:06
1  
This is what I thought to use as well, but please note that this does in-place modification. That's often advantageous but if you don't want it you'll have to make a copy. –  Mr.Wizard Jul 9 at 19:31
    
@Mr.Wizard I agree, now there is something different too :) –  Kuba Jul 9 at 19:42

Although I believe that Kuba's first method is the best approach here is another:

zerofill[a_] := a (1 - BoxMatrix[#/2 - 2, #]) & @ Dimensions @ a

Now:

Array[Times, {5, 8}] // zerofill // MatrixForm

$\left( \begin{array}{cccccccc} 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\ 2 & 0 & 0 & 0 & 0 & 0 & 0 & 16 \\ 3 & 0 & 0 & 0 & 0 & 0 & 0 & 24 \\ 4 & 0 & 0 & 0 & 0 & 0 & 0 & 32 \\ 5 & 10 & 15 & 20 & 25 & 30 & 35 & 40 \end{array} \right)$

share|improve this answer

This performs quite well on large matrices, seems to outrun the others I've tested so far:

Module[{z = ConstantArray[0, Dimensions@#]},
  z[[1, All]] = #[[1, All]];
  z[[All, 1]] = #[[All, 1]];
  z[[-1, All]] = #[[-1, All]];
  z[[All, -1]] = #[[All, -1]];
  z] &

For really large arrays, it would behoove one to work in the sparse domain, where the following is even faster and certainly more memory efficient:

With[{r = First@Dimensions@#, c = Last@Dimensions@#},
  SparseArray[
   Join[Tuples[{{1}, Range@c}], Tuples[{{r}, Range@c}], 
        Tuples[{Range@r, {1}}], Tuples[{Range@r, {c}}]] -> 
    Join[#[[1]], #[[r]], #[[All, 1]], #[[All, c]]], {r, c}]] &
share|improve this answer
    
I never expected this to be faster than x[[2 ;; -2, 2 ;; -2]] but it is! Big +1! –  Mr.Wizard Jul 9 at 23:27
    
@Mr.Wizard: Yes, I was surprised (a bit - I expected faster, just not the degree) - but makes sense - less copy (direct or pointer) involved. I kind of like the update sparse method - even faster than the order of magnitude faster than accepted of the first (would be nice if posters specified they want 'clever' vs efficient)... Thx for +! –  rasher Jul 10 at 4:32
    
@rasher I'm sorry, I tested your code (and upvoted it), but I don't have enough experience to make reliable speed comparisons. –  eldo Jul 11 at 1:21
n = Dimensions[x];
ReplacePart[x, {i_, j_} /;2 <= i <= n[[1]] - 1 && 2 <= j <= n[[2]] - 1 :> 0]

another way:

MapAt[0 &, x, {2 ;; -2, 2 ;; -2}]
share|improve this answer
2  
+1. Just 0 & is enough. –  Pickett Jul 9 at 20:07
    
@ Pickett, thanks for the tip :) –  Algohi Jul 9 at 20:18
    
@kuba, thanks,I have modified it for non square matrices. –  Algohi Jul 9 at 20:23

A variation on @rasher's post:

border = Module[{a = ConstantArray[0, Dimensions@#], i = {1, -1}}, 
                {a[[i]], a[[All, i]]} = {#[[i]], #[[All, i]]}; a] &

border@x //MatrixForm

enter image description here

and another SparseArray variation

border2 = Module[{a = ConstantArray[0, Dimensions@# - 2], d = Dimensions@#}, 
                  # SparseArray[Band[{2, 2}] -> a, d, 1]] &
share|improve this answer
       # ArrayPad[ConstantArray[0, Dimensions@# - 2], 1, 1] &@ 
             Array[Times, {5, 8}] 

or

       # SparseArray[# -> 1 & /@
           Flatten[{#, Reverse@# } &@ 
                  {_, #} & /@ {1, -1}, 1],
                    Dimensions@#] &@  Array[Times, {5, 8}] 
share|improve this answer

All the good answers are given. For fun, here is one using SparseArray

 {n, m} = Dimensions[x];
 x = SparseArray[{{i_, j_} /; j == 1||j == m||i == 1||i == n} :> {x[[i, j]]}, {n, m}];
 MatrixForm[x]

Mathematica graphics

share|improve this answer
    
@Kuba good point, easy to fix, will do in sec –  Nasser Jul 10 at 7:53

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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