7

There are similar questions to this on the forum but none fit the purpose here:

I would like to extract certain elements of a matrix depending on whether a factor is present or not, and create another matrix of the same size with those elements and zeros everywhere else. For example, given

\begin{equation} \left [ \begin{array}{c c} a x & b x^2 \\ c y & d y^2 \end{array} \right ] \end{equation}

I would like to create a new matrix with just the elements that have $x^2$ as a member and zeros everywhere else.

\begin{equation} \left [ \begin{array}{c c} 0 & b x^2 \\ 0 & 0 \end{array} \right ] \end{equation}

I've tried variants of things like this but can't get it to work

SIGMA = {{ a x , b x^2},{c y , d y^2}};

SIGMAx2 = Select[SIGMA , MemberQ[#, x^2] &];
Luap Nalehw
  • 846
  • 5
  • 12

5 Answers5

12

Using Replace (assuming you only want to replace on level 2, as you mention "matrix"):

Using Except

My first version (I kept this version to point out the usage/impact of Orderless)

Replace[SIGMA, Except[HoldPattern[___ x^2 ___]] -> 0, {2}]

{{0, b x^2}, {0, 0}}

Improved version, thanks to Leonid

Replace[SIGMA, Except[___ x^2] -> 0, {2}]

as he explains below, this can be done since Times is Orderless.

Version using FreeQ

Thanks to @ssch, we have a similar version, which is more general:

Replace[SIGMA, a_ /; FreeQ[a, x^2] -> 0, {2}]
Pinguin Dirk
  • 6,519
  • 1
  • 26
  • 36
  • (it should be fine now, I forgot the HoldPattern. Please let me know if it isn't) – Pinguin Dirk Sep 18 '13 at 14:07
  • 3
    +1. Note that Times is Orderless, therefore you don't need two blanks. This in turn allows to ditch HoldPattern, so that you could just use: Replace[SIGMA, Except[___ x^2 ] -> 0, {2}]. – Leonid Shifrin Sep 18 '13 at 14:40
  • ah, I had it that way in the beginning - then I added the second blank (obviously not thinking of Orderless) which screwed things up (I looked at Trace and couldn't make sense of it). Introducing HoldPattern solved it then (with the 2 blanks) (hence my first commend above). Thanks for pointing that out, @LeonidShifrin – Pinguin Dirk Sep 18 '13 at 14:45
  • No problem at all. This is a minor issue anyway. – Leonid Shifrin Sep 18 '13 at 14:48
  • Well, I was looking at something like: {MatchQ[ x^2 c y, HoldPattern[___ x^2 ___]], MatchQ[ x^2 c y, ___ x^2 ___], MatchQ[ x^2 c y, a___ x^2 b___]}, and couldn't properly make sense of it (2nd vs 3rd), but now it makes sense (looking at Trace). And as Except doesn't allow named patterns, I chose to use HoldPattern. – Pinguin Dirk Sep 18 '13 at 14:54
  • Yes, pattern evaluation is a known issue, can be quite annoying. I seem to remember it being discussed here on SE more than once, but the one I found now is this. – Leonid Shifrin Sep 18 '13 at 15:45
  • 4
    To work for more than Times you can use Replace[m, a_ /; FreeQ[a, x^2] -> 0, {2}] – ssch Sep 18 '13 at 15:46
  • @ssch: you want to post that as seperate answer, or shall I include in mine? – Pinguin Dirk Sep 18 '13 at 15:55
  • @PinguinDirk go ahead and put it in yours, I made a comment because I found it so similar. – ssch Sep 18 '13 at 16:10
  • Thanks a lot. Very Useful indeed. – Luap Nalehw Sep 18 '13 at 23:12
5

For polynomials:

x^2 Coefficient[SIGMA, x, 2]
{{0, b x^2}, {0, 0}}

$\left[ \begin{array}{cc} 0 & b x^2 \\ 0 & 0 \end{array} \right]$

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
3

Maybe something like this:

Map[
    If[Length@Cases[#, x^2, Infinity] > 0, #, 0] &,
    SIGMA,
    {2}]
{{0, b x^2}, {0, 0}}

This solution will work with more complex patterns than Times too.

Kuba
  • 136,707
  • 13
  • 279
  • 740
  • 1
    It would be shorter to use FreeQ as by default that function uses a levelspec of {0, Infinity}: Map[If[FreeQ[#, x^2], 0, #] &, SIGMA, {2}] – Mr.Wizard Sep 18 '13 at 19:47
  • @Mr.Wizard of course, not many solutions would be worse than this :P I just was to hasty and then had a bus. After that, the battle was over :P – Kuba Sep 18 '13 at 19:55
  • Kuba the basic idea is sound, though Replace is a bit cleaner. I'd personally like to see you include the FreeQ form in your answer; I think you'd have arrived at it too given a bit more time to think about it. – Mr.Wizard Sep 18 '13 at 19:57
3
SIGMAx2 = Map[If[MemberQ[#, x^2, Infinity], #, 0] &, SIGMA, {2}]
{{0, b x^2}, {0, 0}}
ybeltukov
  • 43,673
  • 5
  • 108
  • 212
0

Assuming your list as A

 Table[If[(SameQ[A[[i, j]], #]) & /@ Cases[A, _*x^2, Infinity] /. 
       List -> Or, A[[i, j]], 0], {i, Length[A]}, {j, 1, Length[A[[i]]]}]

{{0, b x^2}, {0, 0}}

In case you have more terms matching criteria than it will work as well,

A = {{a x, b x^2}, {c y x^2, d y^2}};

{{0,b x^2},{c x^2 y,0}}

Sjoerd C. de Vries
  • 65,815
  • 14
  • 188
  • 323
Pankaj Sejwal
  • 2,063
  • 14
  • 23