11
$\begingroup$

Is it possible for the Piecewise function to process a vector comparison? For example, my input vector is

x={0,1,2,3,4}

I would like to define a function that gives me x^2 if x<3.5, and x+3 otherwise. i.e. I would like my output to be {0,1,4,9,7}. Here I define a function:

myfunc[x_] := Piecewise[{{x^2,x<3.5},{x+3,x>=3.5}}]

which obviously does not work. Is there a way to let Mathematica know that I want to compare x with 3.5 elementwise and apply that particular value to the segment as appropriate?

I'm used to R programming where I can use the ifelse function for this job, but I'm relatively new to Mathematica and don't know if this is possible.

Thanks!

$\endgroup$
3
  • $\begingroup$ Related question: mathematica.stackexchange.com/questions/2821/… $\endgroup$ Commented Apr 1, 2012 at 11:15
  • $\begingroup$ Thanks for your solutions; all work perfectly. As a R user I don't feel particularly comfortable with the way mathematica handles vector manipulation. Due to the nature of this problem I couldn't think of any keywords to search for a solution effectively. $\endgroup$
    – David L
    Commented Apr 1, 2012 at 16:53
  • 1
    $\begingroup$ Note that solutions using Listable and Map lose the speed advantage offered by vectorized operations in Mathematica. If speed is important, you may wish to use things like UnitStep and Unitize instead. $\endgroup$ Commented Apr 1, 2012 at 16:57

2 Answers 2

9
$\begingroup$

I'm not in front of a computer now, but I think you should be able to set your function to Listable and use it as-is:

SetAttributes[myfunc, Listable]
$\endgroup$
2
  • 1
    $\begingroup$ I am in front of a computer. It works. $\endgroup$
    – yohbs
    Commented Apr 1, 2012 at 12:48
  • $\begingroup$ @yohbs: Thanks! $\endgroup$
    – Cassini
    Commented Apr 1, 2012 at 18:41
9
$\begingroup$

There is nothing wrong with your function. You can Map it to a list as

 myfunc/@{0,1,2,3,4} 

you get your desired output.

Alternatively, you can use your myfunc to define a new function that accepts lists:

 mynewfunc[y_List] := Map[myfunc, y]

Now

 mynewfunc[{0,1,2,3,4}]

gives

 {0, 1, 4, 9, 7}
$\endgroup$
3
  • $\begingroup$ Should it work for a multivariate function that is being evaluated element-wise of two vectors? Because I have a piecewise function of two variables and I want to map two vectors on it but I can't make it work using the suggestion above. $\endgroup$
    – Laura K
    Commented Feb 5, 2018 at 14:54
  • $\begingroup$ @LauraK, I think you can use Apply (@@@) instead of Map (/@) in the case you describe. For example, given ClearAll[myfunc]; myfunc[x_, y_] := Piecewise[{{x^2 + y, x + y < 10}, {x + 3, y > 5}}]; and an input list of pairs, say, xylist = RandomInteger[9, {5, 2}], you can do myfunc @@@ xylist or mynewfunc[y_List] := Apply[myfunc, y, {1}]; mynewfunc[xylist] to get the same result. $\endgroup$
    – kglr
    Commented Feb 5, 2018 at 18:23
  • $\begingroup$ It worked. Thank you very much, @kglr! $\endgroup$
    – Laura K
    Commented Feb 5, 2018 at 19:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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